From 83eea8793043c47c799193cefe92765a7281dea8 Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Wed, 22 Jul 2026 22:35:44 +0800 Subject: [PATCH 1/4] [skip ci] Update UPGRADING.INTERNALS for #21607 --- UPGRADING.INTERNALS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index ef5155e39db6..666d7830a5f8 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -145,6 +145,9 @@ PHP 8.6 INTERNALS UPGRADE NOTES (sendfile, splice, copy_file_range, TransmitFile), and is now used by php_stream_copy_to_stream_ex(). The mmap-based copy fallback was removed. . Added zend_string_equals_cstr_ci(). + . Added zend_cstr_append_char(), zend_cstr_concat(), and + zend_cstr_concat3() as helper functions to allocate NUL-terminated raw C + strings from one or more buffers. . Added zend_string_ends_with() and related variants. . Added trait support for internal classes. From b06dfa2acaabd6b39baa5b2583038984717a1d2e Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 22 Jul 2026 19:03:51 +0200 Subject: [PATCH 2/4] Fix #22859 undefined symbol 'zip_file_set_encryption' (#22861) Only when HAVE_ENCRYPTION is true, we can use the zip_file_set_encryption function. This commit add a guard to the zip_file_set_encryption symbol. --- ext/zip/php_zip.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 48075ac0ec6b..a41007b7aa89 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -82,6 +82,7 @@ static bool php_zip_set_file_comment(struct zip *za, zip_uint64_t index, const c # define add_ascii_assoc_string add_assoc_string # define add_ascii_assoc_long add_assoc_long +#ifdef HAVE_ENCRYPTION static bool php_zip_file_set_encryption(struct zip *intern, zend_long index, zend_long method, char *password) { // FIXME: is a workaround to reset/free the password in case of consecutive calls. // when libzip 1.11.5 is available, we can save this call in this case. @@ -92,6 +93,7 @@ static bool php_zip_file_set_encryption(struct zip *intern, zend_long index, zen return (zip_file_set_encryption(intern, (zip_uint64_t)index, (zip_uint16_t)method, password) == 0); } +#endif /* Flatten a path by making a relative path (to .)*/ static char * php_zip_make_relative_path(char *path, size_t path_len) /* {{{ */ From 77a7d34ab26676a318eba6172b5f4dc19dc7c051 Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Wed, 22 Jul 2026 16:18:36 -0300 Subject: [PATCH 3/4] Fix GH-22849: error_include_args=1 mishandled for include() (#22851) include and friends aren't functions, but constructs of the engine. Special-case them and snarf their argument for display. --- Zend/tests/gh22849.phpt | 31 +++++++++++++++++++++++++++++++ Zend/zend_exceptions.c | 13 +++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 Zend/tests/gh22849.phpt diff --git a/Zend/tests/gh22849.phpt b/Zend/tests/gh22849.phpt new file mode 100644 index 000000000000..a38c64baf542 --- /dev/null +++ b/Zend/tests/gh22849.phpt @@ -0,0 +1,31 @@ +--TEST-- +PHP 8.6 error_include_args=1 mishandled for include() +--INI-- +error_include_args=On +--FILE-- + +--EXPECTF-- +Warning: include('does not exist'): Failed to open stream: No such file or directory in %s on line %d + +Warning: include('does not exist'): Failed opening 'does not exist' for inclusion (include_path='%s') in %s on line %d + +Warning: include_once('does not exist'): Failed to open stream: No such file or directory in %s on line %d + +Warning: include_once('does not exist'): Failed opening 'does not exist' for inclusion (include_path='%s') in %s on line %d + +Warning: require('does not exist'): Failed to open stream: No such file or directory in %s on line %d + +Fatal error: Uncaught Error: Failed opening required 'does not exist' (include_path='%s') in %s:%d +Stack trace: +#0 %s(%d): foo(1, 2) +#1 {main} + thrown in %s on line %d diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index a1301b8c20b2..ca91ec0ce12b 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -630,6 +630,19 @@ ZEND_API zend_string *zend_trace_function_args_to_string(const HashTable *frame) /* {{{ Gets the currently executing function's arguments as a string. Used by php_verror. */ ZEND_API zend_string *zend_trace_current_function_args_string(void) { zend_string *dynamic_params = NULL; + /* Special case: require_once/include_once aren't functions, but we + * want to capture their arguments anyways, for i.e. file not found. + */ + zend_execute_data *execute_data = EG(current_execute_data); + if (execute_data && execute_data->func + && ZEND_USER_CODE(execute_data->func->common.type) + && (execute_data->opline->opcode == ZEND_INCLUDE_OR_EVAL)) { + zval *inc_filename = RT_CONSTANT(execute_data->opline, execute_data->opline->op1); + smart_str str = {0}; + build_trace_args(inc_filename, &str); + return smart_str_extract(&str); + } + /* get a backtrace to snarf function args */ zval backtrace; zend_fetch_debug_backtrace(&backtrace, /* skip_last */ 0, /* options */ 0, /* limit */ 1); From ae487f4f666ec4d59baa4c42c577ccdf6574a6e5 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Wed, 22 Jul 2026 22:16:42 +0200 Subject: [PATCH 4/4] Add $salt_length param to openssl_sign and openssl_verify (#20681) This allows controlling the RSA-PSS salt length and enforcing an expected salt length when verifying. It also adds OPENSSL_RSA_PSS_SALTLEN_* constants. This is needed for some application. Custom TLS implementation is one example --- NEWS | 2 ++ UPGRADING | 9 ++++++ ext/openssl/openssl.c | 35 +++++++++++++++++++-- ext/openssl/openssl.stub.php | 20 ++++++++++-- ext/openssl/openssl_arginfo.h | 7 ++++- ext/openssl/tests/openssl_sign_basic.phpt | 9 +++++- ext/openssl/tests/openssl_verify_basic.phpt | 14 +++++++++ 7 files changed, 89 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index 217d6b959c81..3c5101c096cb 100644 --- a/NEWS +++ b/NEWS @@ -132,6 +132,8 @@ PHP NEWS preloaded trait). (iliaal) - OpenSSL: + . Added $salt_length parameter to openssl_sign() and openssl_verify() with + new OPENSSL_RSA_PSS_SALTLEN_* constants. (Jakub Zelenka) . Fixed timeout for supplemental read at end of a blocking stream in SSL stream wrapper. (ilutov) . Fixed stream_socket_get_crypto_status() after supplemental read. (ilutov) diff --git a/UPGRADING b/UPGRADING index 077a7faf6562..97670e09246d 100644 --- a/UPGRADING +++ b/UPGRADING @@ -383,6 +383,10 @@ PHP 8.6 UPGRADE NOTES - OpenSSL: . Output of openssl_x509_parse() contains criticalExtensions listing all critical certificate extensions. + . openssl_sign() and openssl_verify() now have an additional optional + argument $salt_length that allows controlling the RSA-PSS salt length + when OPENSSL_PKCS1_PSS_PADDING is used. It accepts an explicit length or + one of the new OPENSSL_RSA_PSS_SALTLEN_* constants. - PDO_DBLIB: . When using persistent connections, there is now a liveness check in the @@ -513,6 +517,11 @@ PHP 8.6 UPGRADE NOTES . CURL_SEEKFUNC_FAIL. . CURL_SEEKFUNC_CANTSEEK. +- OpenSSL: + . OPENSSL_RSA_PSS_SALTLEN_DIGEST. + . OPENSSL_RSA_PSS_SALTLEN_AUTO. + . OPENSSL_RSA_PSS_SALTLEN_MAX. + - Sockets: . TCP_USER_TIMEOUT (Linux only). . AF_UNSPEC. diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index fa91f232bcdf..a3d8edd4c8d4 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -4525,6 +4525,27 @@ static zend_result php_openssl_setup_rsa_padding(EVP_PKEY_CTX *pctx, EVP_PKEY *p return SUCCESS; } +static zend_result php_openssl_setup_rsa_pss_salt_length(EVP_PKEY_CTX *pctx, EVP_PKEY *pkey, zend_long padding, zend_long salt_length) +{ + /* Only apply if using PSS padding */ + if (padding != RSA_PKCS1_PSS_PADDING) { + return SUCCESS; + } + + /* Only apply to RSA keys */ + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA && EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA_PSS) { + return SUCCESS; + } + + if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, (int)salt_length) <= 0) { + php_openssl_store_errors(); + php_error_docref(NULL, E_WARNING, "Could not set RSA-PSS salt length"); + return FAILURE; + } + + return SUCCESS; +} + /* {{{ Signs data */ PHP_FUNCTION(openssl_sign) { @@ -4538,16 +4559,18 @@ PHP_FUNCTION(openssl_sign) zend_long method_long = OPENSSL_ALGO_SHA1; const EVP_MD *mdtype; zend_long padding = 0; + zend_long salt_length = RSA_PSS_SALTLEN_AUTO; EVP_PKEY_CTX *pctx; bool can_default_digest = ZEND_THREEWAY_COMPARE(PHP_OPENSSL_API_VERSION, 0x30000) >= 0; - ZEND_PARSE_PARAMETERS_START(3, 5) + ZEND_PARSE_PARAMETERS_START(3, 6) Z_PARAM_STRING(data, data_len) Z_PARAM_ZVAL(signature) Z_PARAM_ZVAL(key) Z_PARAM_OPTIONAL Z_PARAM_STR_OR_LONG(method_str, method_long) Z_PARAM_LONG(padding) + Z_PARAM_LONG(salt_length) ZEND_PARSE_PARAMETERS_END(); pkey = php_openssl_pkey_from_zval(key, 0, "", 0, 3); @@ -4568,12 +4591,14 @@ PHP_FUNCTION(openssl_sign) php_error_docref(NULL, E_WARNING, "Unknown digest algorithm"); RETURN_FALSE; } + PHP_OPENSSL_CHECK_LONG_TO_INT(salt_length, salt_length, 6); md_ctx = EVP_MD_CTX_create(); size_t siglen; if (md_ctx != NULL && EVP_DigestSignInit(md_ctx, &pctx, mdtype, NULL, pkey) && php_openssl_setup_rsa_padding(pctx, pkey, padding) == SUCCESS && + php_openssl_setup_rsa_pss_salt_length(pctx, pkey, padding, salt_length) == SUCCESS && EVP_DigestSign(md_ctx, NULL, &siglen, (unsigned char*)data, data_len) && (sigbuf = zend_string_alloc(siglen, 0)) != NULL && EVP_DigestSign(md_ctx, (unsigned char*)ZSTR_VAL(sigbuf), &siglen, (unsigned char*)data, data_len)) { @@ -4607,19 +4632,22 @@ PHP_FUNCTION(openssl_verify) zend_string *method_str = NULL; zend_long method_long = OPENSSL_ALGO_SHA1; zend_long padding = 0; + zend_long salt_length = RSA_PSS_SALTLEN_AUTO; EVP_PKEY_CTX *pctx; bool can_default_digest = ZEND_THREEWAY_COMPARE(PHP_OPENSSL_API_VERSION, 0x30000) >= 0; - ZEND_PARSE_PARAMETERS_START(3, 5) + ZEND_PARSE_PARAMETERS_START(3, 6) Z_PARAM_STRING(data, data_len) Z_PARAM_STRING(signature, signature_len) Z_PARAM_ZVAL(key) Z_PARAM_OPTIONAL Z_PARAM_STR_OR_LONG(method_str, method_long) Z_PARAM_LONG(padding) + Z_PARAM_LONG(salt_length) ZEND_PARSE_PARAMETERS_END(); PHP_OPENSSL_CHECK_SIZE_T_TO_UINT(signature_len, signature, 2); + PHP_OPENSSL_CHECK_LONG_TO_INT(salt_length, salt_length, 6); if (method_str) { mdtype = php_openssl_get_evp_md_by_name(ZSTR_VAL(method_str)); @@ -4648,7 +4676,8 @@ PHP_FUNCTION(openssl_verify) } if (!EVP_DigestVerifyInit(md_ctx, &pctx, mdtype, NULL, pkey) || - php_openssl_setup_rsa_padding(pctx, pkey, padding) == FAILURE) { + php_openssl_setup_rsa_padding(pctx, pkey, padding) == FAILURE || + php_openssl_setup_rsa_pss_salt_length(pctx, pkey, padding, salt_length) == FAILURE) { php_openssl_store_errors(); err = -1; goto cleanup; diff --git a/ext/openssl/openssl.stub.php b/ext/openssl/openssl.stub.php index 6080ac323903..3d3fa3ea634f 100644 --- a/ext/openssl/openssl.stub.php +++ b/ext/openssl/openssl.stub.php @@ -323,6 +323,22 @@ public function __unserialize(array $data): void {} */ const OPENSSL_PKCS1_PSS_PADDING = UNKNOWN; +/** + * @var int + * @cvalue RSA_PSS_SALTLEN_DIGEST + */ +const OPENSSL_RSA_PSS_SALTLEN_DIGEST = UNKNOWN; +/** + * @var int + * @cvalue RSA_PSS_SALTLEN_AUTO + */ +const OPENSSL_RSA_PSS_SALTLEN_AUTO = UNKNOWN; +/** + * @var int + * @cvalue RSA_PSS_SALTLEN_MAX + */ +const OPENSSL_RSA_PSS_SALTLEN_MAX = UNKNOWN; + /* Informational stream wrapper constants */ /** @@ -679,10 +695,10 @@ function openssl_error_string(): string|false {} * @param string $signature * @param OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $private_key */ -function openssl_sign(string $data, &$signature, #[\SensitiveParameter] $private_key, string|int $algorithm = OPENSSL_ALGO_SHA1, int $padding = 0): bool {} +function openssl_sign(string $data, &$signature, #[\SensitiveParameter] $private_key, string|int $algorithm = OPENSSL_ALGO_SHA1, int $padding = 0, int $salt_length = OPENSSL_RSA_PSS_SALTLEN_AUTO): bool {} /** @param OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $public_key */ -function openssl_verify(string $data, string $signature, $public_key, string|int $algorithm = OPENSSL_ALGO_SHA1, int $padding = 0): int|false {} +function openssl_verify(string $data, string $signature, $public_key, string|int $algorithm = OPENSSL_ALGO_SHA1, int $padding = 0, int $salt_length = OPENSSL_RSA_PSS_SALTLEN_AUTO): int|false {} /** * @param string $sealed_data diff --git a/ext/openssl/openssl_arginfo.h b/ext/openssl/openssl_arginfo.h index caf47a256e78..b1742dcb05f8 100644 --- a/ext/openssl/openssl_arginfo.h +++ b/ext/openssl/openssl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit openssl.stub.php instead. - * Stub hash: 4d38e81a2f73bb6dd4bbe7a3e0b8ba86600654e2 */ + * Stub hash: 7cad995b734d69f98d489edb97a7878a4ea8f47e */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_openssl_x509_export_to_file, 0, 2, _IS_BOOL, 0) ZEND_ARG_OBJ_TYPE_MASK(0, certificate, OpenSSLCertificate, MAY_BE_STRING, NULL) @@ -285,6 +285,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_openssl_sign, 0, 3, _IS_BOOL, 0) ZEND_ARG_INFO(0, private_key) ZEND_ARG_TYPE_MASK(0, algorithm, MAY_BE_STRING|MAY_BE_LONG, "OPENSSL_ALGO_SHA1") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, padding, IS_LONG, 0, "0") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, salt_length, IS_LONG, 0, "OPENSSL_RSA_PSS_SALTLEN_AUTO") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_openssl_verify, 0, 3, MAY_BE_LONG|MAY_BE_FALSE) @@ -293,6 +294,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_openssl_verify, 0, 3, MAY_BE_LON ZEND_ARG_INFO(0, public_key) ZEND_ARG_TYPE_MASK(0, algorithm, MAY_BE_STRING|MAY_BE_LONG, "OPENSSL_ALGO_SHA1") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, padding, IS_LONG, 0, "0") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, salt_length, IS_LONG, 0, "OPENSSL_RSA_PSS_SALTLEN_AUTO") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_openssl_seal, 0, 5, MAY_BE_LONG|MAY_BE_FALSE) @@ -676,6 +678,9 @@ static void register_openssl_symbols(int module_number) REGISTER_LONG_CONSTANT("OPENSSL_NO_PADDING", RSA_NO_PADDING, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_OAEP_PADDING", RSA_PKCS1_OAEP_PADDING, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_PSS_PADDING", RSA_PKCS1_PSS_PADDING, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("OPENSSL_RSA_PSS_SALTLEN_DIGEST", RSA_PSS_SALTLEN_DIGEST, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("OPENSSL_RSA_PSS_SALTLEN_AUTO", RSA_PSS_SALTLEN_AUTO, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("OPENSSL_RSA_PSS_SALTLEN_MAX", RSA_PSS_SALTLEN_MAX, CONST_PERSISTENT); REGISTER_STRING_CONSTANT("OPENSSL_DEFAULT_STREAM_CIPHERS", OPENSSL_DEFAULT_STREAM_CIPHERS, CONST_PERSISTENT); #if !defined(OPENSSL_NO_RC2) REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_RC2_40", PHP_OPENSSL_CIPHER_RC2_40, CONST_PERSISTENT); diff --git a/ext/openssl/tests/openssl_sign_basic.phpt b/ext/openssl/tests/openssl_sign_basic.phpt index 9d2edbec59f7..d8880a6a1899 100644 --- a/ext/openssl/tests/openssl_sign_basic.phpt +++ b/ext/openssl/tests/openssl_sign_basic.phpt @@ -7,7 +7,6 @@ openssl $data = "Testing openssl_sign()"; $privkey = "file://" . __DIR__ . "/private_rsa_1024.key"; $wrong = "wrong"; - var_dump(openssl_sign($data, $sign1, $privkey, OPENSSL_ALGO_SHA256)); var_dump(bin2hex($sign1)); var_dump(openssl_sign($data, $sign2, $privkey, OPENSSL_ALGO_SHA256)); @@ -17,6 +16,10 @@ var_dump(strlen($sign1)); var_dump(openssl_sign($data, $sign2, $privkey, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING)); var_dump(strlen($sign2)); var_dump($sign1 === $sign2); +var_dump(openssl_sign($data, $sign3, $privkey, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING, OPENSSL_RSA_PSS_SALTLEN_DIGEST)); +var_dump(strlen($sign3)); +var_dump(openssl_sign($data, $sign4, $privkey, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING, 32)); +var_dump(strlen($sign4)); var_dump(openssl_sign($data, $sign, $wrong)); ?> --EXPECTF-- @@ -29,6 +32,10 @@ int(128) bool(true) int(128) bool(false) +bool(true) +int(128) +bool(true) +int(128) Warning: openssl_sign(): Supplied key param cannot be coerced into a private key in %s on line %d bool(false) diff --git a/ext/openssl/tests/openssl_verify_basic.phpt b/ext/openssl/tests/openssl_verify_basic.phpt index 1b28c1371083..3bcf3ba0e66f 100644 --- a/ext/openssl/tests/openssl_verify_basic.phpt +++ b/ext/openssl/tests/openssl_verify_basic.phpt @@ -13,6 +13,14 @@ $wrong = "wrong"; openssl_sign($data, $sign, $privkey, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING); var_dump(openssl_verify($data, $sign, $pubkey, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING)); var_dump(openssl_verify($data, $sign, $pubkey, OPENSSL_ALGO_SHA256)); +openssl_sign($data, $sign_pss, $privkey, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING, OPENSSL_RSA_PSS_SALTLEN_DIGEST); +var_dump(openssl_verify($data, $sign_pss, $pubkey, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING, OPENSSL_RSA_PSS_SALTLEN_DIGEST)); +var_dump(openssl_verify($data, $sign_pss, $pubkey, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING, 32)); +var_dump(openssl_verify($data, $sign_pss, $pubkey, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING, OPENSSL_RSA_PSS_SALTLEN_AUTO)); +var_dump(openssl_verify($data, $sign_pss, $pubkey, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING, 20)); +openssl_sign($data, $sign_pss, $privkey, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING, OPENSSL_RSA_PSS_SALTLEN_MAX); +var_dump(openssl_verify($data, $sign_pss, $pubkey, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING, OPENSSL_RSA_PSS_SALTLEN_MAX)); +var_dump(openssl_verify($data, $sign_pss, $pubkey, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING, OPENSSL_RSA_PSS_SALTLEN_DIGEST)); openssl_sign($data, $sign, $privkey, OPENSSL_ALGO_SHA256); var_dump(openssl_verify($data, $sign, $pubkey, OPENSSL_ALGO_SHA256)); var_dump(openssl_verify($data, $sign, $privkey, OPENSSL_ALGO_SHA256)); @@ -24,6 +32,12 @@ var_dump(openssl_verify($wrong, $sign, $pubkey, OPENSSL_ALGO_SHA256)); int(1) int(0) int(1) +int(1) +int(1) +int(0) +int(1) +int(0) +int(1) Warning: openssl_verify(): Supplied key param cannot be coerced into a public key in %s on line %d bool(false)