濮阳杆衣贸易有限公司

主頁 > 知識(shí)庫 > 詳解PHP版本兼容之openssl調(diào)用參數(shù)

詳解PHP版本兼容之openssl調(diào)用參數(shù)

熱門標(biāo)簽:拉薩打電話機(jī)器人 h5 地圖標(biāo)注 合肥外呼系統(tǒng)app 沈陽人工智能電銷機(jī)器人公司 高識(shí)別電銷機(jī)器人 智能外呼電銷系統(tǒng) 電銷機(jī)器人-快迭智能 寶安400電話辦理 哈爾濱400電話辦理到易號(hào)網(wǎng)

背景與問題解決方式

老項(xiàng)目重構(gòu)支付寶部分代碼整合支付寶新的sdk時(shí)發(fā)現(xiàn)驗(yàn)簽總是失敗,才發(fā)現(xiàn)是open_verify最后的參數(shù)傳輸問題。而open_sign同樣如此。本文主要說明open_verify的解決方式和代碼解析。而問題的解決方式也是修改最后的加密類型參數(shù),解決方式代碼如下:

// 將最后的常量OPENSSL_ALGO_SHA256修改成字符串
openssl_verify($data, base64_decode($sign), $res, "sha256WithRSAEncryption");

官方文檔解釋

上面只說了問題的出現(xiàn)與對(duì)應(yīng)的解決方式,如果有興趣繼續(xù)了解該函數(shù)的,可以繼續(xù)往下讀,首先來看下官方文檔對(duì)此函數(shù)的解釋。

int openssl_verify ( string $data , string $signature , mixed $pub_key_id [, mixed $signature_alg = OPENSSL_ALGO_SHA1 ] )

參數(shù)注釋

data

以前用來生成簽名的數(shù)據(jù)字符串。

signature

原始二進(jìn)制字符串,通過openssl_sign()或類似的函數(shù)生成。

pub_key_id

resource - 一個(gè)密鑰, 通過 openssl_get_publickey() 函數(shù)返回。

string - 一個(gè) PEM 格式的密鑰, 比如, “—–BEGIN PUBLIC KEY—– MIIBCgK…”

signature_alg

int - 以下簽名算法之一Signature Algorithms.

string - 由openssl_get_md_methods()函數(shù)返回的可用字符串,比如, “sha1WithRSAEncryption” 或者 “sha512”.
官方文檔給出的signature_alg參數(shù)可以為int或者string類型,int類型直接調(diào)用對(duì)應(yīng)的枚舉值,string則是openssl_get_md_methods函數(shù)返回的可用字符串,調(diào)用openssl_get_md_methods方法打印參數(shù)如下,而這些字符串也是對(duì)應(yīng)加密方式的摘要信息,后文源碼中可能會(huì)看的對(duì)函數(shù)調(diào)用稍微明白那么一丟丟。

Array
(
[0] => DSA
[1] => DSA-SHA
[2] => DSA-SHA1
[3] => DSA-SHA1-old
[4] => DSS1
[5] => GOST 28147-89 MAC
[6] => GOST R 34.11-94
[7] => MD4
[8] => MD5
[9] => MDC2
[10] => RIPEMD160
[11] => RSA-MD4
[12] => RSA-MD5
[13] => RSA-MDC2
[14] => RSA-RIPEMD160
[15] => RSA-SHA
[16] => RSA-SHA1
[17] => RSA-SHA1-2
[18] => RSA-SHA224
[19] => RSA-SHA256
[20] => RSA-SHA384
[21] => RSA-SHA512
[22] => SHA
[23] => SHA1
[24] => SHA224
[25] => SHA256
[26] => SHA384
[27] => SHA512
[28] => dsaEncryption
[29] => dsaWithSHA
[30] => dsaWithSHA1
[31] => dss1
[32] => ecdsa-with-SHA1
[33] => gost-mac
[34] => md4
[35] => md4WithRSAEncryption
[36] => md5
[37] => md5WithRSAEncryption
[38] => md_gost94
[39] => mdc2
[40] => mdc2WithRSA
[41] => ripemd
[42] => ripemd160
[43] => ripemd160WithRSA
[44] => rmd160
[45] => sha
[46] => sha1
[47] => sha1WithRSAEncryption
[48] => sha224
[49] => sha224WithRSAEncryption
[50] => sha256
[51] => sha256WithRSAEncryption
[52] => sha384
[53] => sha384WithRSAEncryption
[54] => sha512
[55] => sha512WithRSAEncryption
[56] => shaWithRSAEncryption
[57] => ssl2-md5
[58] => ssl3-md5
[59] => ssl3-sha1
[60] => whirlpool
)

由此也可看出函數(shù)是兼容兩種模式的,但是為什么php版本會(huì)有兼容問題么?在openssl庫版本是一致的情況下,接下來的原因應(yīng)該只遺留在php擴(kuò)展的問題上。那下面來看看對(duì)應(yīng)的源碼去發(fā)現(xiàn)問題出現(xiàn)在哪吧。

函數(shù)源碼

openssl_verify函數(shù)源碼

openssl_verify源碼中有這樣一段,如果參數(shù)method為string類型的時(shí)候,調(diào)用openssl庫的EVP_get_digestbyname方法,在網(wǎng)上查看了下此方法的作用,主要是根據(jù)摘要信息返回
EVP_MD結(jié)構(gòu),而EVP_get_digestbyname方法由于是openssl庫源代碼并且對(duì)C語言知之甚少,熊某就沒去查看,
只是了解php代碼調(diào)用背后的一些處理邏輯,有興趣的可以看看openssl庫的代碼實(shí)現(xiàn)。

if (method == NULL || Z_TYPE_P(method) == IS_LONG) {
    if (method != NULL) {
      signature_algo = Z_LVAL_P(method);
    }
    mdtype = php_openssl_get_evp_md_from_algo(signature_algo);
  } else if (Z_TYPE_P(method) == IS_STRING) {
    mdtype = EVP_get_digestbyname(Z_STRVAL_P(method));
  } else {
    php_error_docref(NULL, E_WARNING, "Unknown signature algorithm.");
    RETURN_FALSE;
  }

原來是枚舉值的問題?

一開始本人以為php5.3版本會(huì)是method參數(shù)類型的限制,一看源代碼才發(fā)現(xiàn),openssl_verify函數(shù)的實(shí)現(xiàn)邏輯是一致的,都是檢測(cè)method參數(shù)類型,那么問題就不出現(xiàn)在參數(shù)類型上,然后我查看了參數(shù)為long類型是所調(diào)用的php_openssl_get_evp_md_from_algo函數(shù),果然發(fā)現(xiàn)了問題所在。源碼如下:

php5.3.27

static EVP_MD * php_openssl_get_evp_md_from_algo(long algo) { /* {{{ */
  EVP_MD *mdtype;

  switch (algo) {
    case OPENSSL_ALGO_SHA1:
      mdtype = (EVP_MD *) EVP_sha1();
      break;
    case OPENSSL_ALGO_MD5:
      mdtype = (EVP_MD *) EVP_md5();
      break;
    case OPENSSL_ALGO_MD4:
      mdtype = (EVP_MD *) EVP_md4();
      break;
#ifdef HAVE_OPENSSL_MD2_H
    case OPENSSL_ALGO_MD2:
      mdtype = (EVP_MD *) EVP_md2();
      break;
#endif
    case OPENSSL_ALGO_DSS1:
      mdtype = (EVP_MD *) EVP_dss1();
      break;
    default:
      return NULL;
      break;
  }
  return mdtype;
}

php7.1.18

static EVP_MD * php_openssl_get_evp_md_from_algo(zend_long algo) { /* {{{ */
  EVP_MD *mdtype;

  switch (algo) {
    case OPENSSL_ALGO_SHA1:
      mdtype = (EVP_MD *) EVP_sha1();
      break;
    case OPENSSL_ALGO_MD5:
      mdtype = (EVP_MD *) EVP_md5();
      break;
    case OPENSSL_ALGO_MD4:
      mdtype = (EVP_MD *) EVP_md4();
      break;
#ifdef HAVE_OPENSSL_MD2_H
    case OPENSSL_ALGO_MD2:
      mdtype = (EVP_MD *) EVP_md2();
      break;
#endif
#if OPENSSL_VERSION_NUMBER  0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
    case OPENSSL_ALGO_DSS1:
      mdtype = (EVP_MD *) EVP_dss1();
      break;
#endif
    case OPENSSL_ALGO_SHA224:
      mdtype = (EVP_MD *) EVP_sha224();
      break;
    case OPENSSL_ALGO_SHA256:
      mdtype = (EVP_MD *) EVP_sha256();
      break;
    case OPENSSL_ALGO_SHA384:
      mdtype = (EVP_MD *) EVP_sha384();
      break;
    case OPENSSL_ALGO_SHA512:
      mdtype = (EVP_MD *) EVP_sha512();
      break;
    case OPENSSL_ALGO_RMD160:
      mdtype = (EVP_MD *) EVP_ripemd160();
      break;
    default:
      return NULL;
      break;
  }
  return mdtype;
}

由上面源代碼可以很清晰的發(fā)現(xiàn)問題所在,隨著php版本的升級(jí),其所在的openssl擴(kuò)展對(duì)應(yīng)的調(diào)用條件也增加了很多,最后導(dǎo)致上述問題的源碼也只是switch…case少了幾個(gè)條件,在此也希望大家發(fā)現(xiàn)問題的時(shí)候,可以先去解決問題,然后有興趣的話可以去查看源代碼分析下問題所導(dǎo)致的原因。

您可能感興趣的文章:
  • 使用openssl 生成免費(fèi)證書的方法步驟
  • 升級(jí) PHP7.1 后 openssl 解密 mcrypt AES 數(shù)據(jù)不兼容問題的處理方法
  • PHP7.1中使用openssl替換mcrypt的實(shí)例詳解
  • linux環(huán)境下安裝PHP的OpenSSL擴(kuò)展的方法講解
  • php7安裝openssl擴(kuò)展方法
  • 詳解Linux(centos7)下安裝OpenSSL安裝圖文方法
  • Linux下Nginx安裝的方法(pcre和openssl)
  • Openssl實(shí)現(xiàn)雙向認(rèn)證教程(附服務(wù)端客戶端代碼)

標(biāo)簽:林芝 山東 威海 巴中 泰州 張家口 成都 梅州

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《詳解PHP版本兼容之openssl調(diào)用參數(shù)》,本文關(guān)鍵詞  詳解,PHP,版本,兼容,之,openssl,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《詳解PHP版本兼容之openssl調(diào)用參數(shù)》相關(guān)的同類信息!
  • 本頁收集關(guān)于詳解PHP版本兼容之openssl調(diào)用參數(shù)的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    寿宁县| 乌兰浩特市| 宁阳县| 青冈县| 莱州市| 元谋县| 体育| 贞丰县| 新津县| 徐水县| 龙泉市| 肇庆市| 沾化县| 定结县| 南昌市| 贵州省| 丹东市| 石嘴山市| 体育| 阳原县| 长顺县| 岳普湖县| 德安县| 浮梁县| 泰来县| 克拉玛依市| 平利县| 永胜县| 荥阳市| 屯留县| 绥宁县| 刚察县| 南昌市| 保德县| 淳化县| 晋城| 县级市| 南开区| 东宁县| 焦作市| 河池市|