规范影室闪光灯

配置参数

  • 特色:金贝 MSN V-800 专业影室闪光灯 1/8000s 高速闪光 持续时间

查看完整参数>>

1. Math 对象

背景与问题解决方式

1.1 介绍

老项目重构支付宝部分代码整合支付宝新的sdk时发现验签总是失败,才发现是open_verify最后的参数传输问题。而open_sign同样如此。本文主要说明open_verify的解决方式和代码解析。而问题的解决方式也是修改最后的加密类型参数,解决方式代码如下:

Math 对象,是数学对象,提供对数据的数学计算,如:获取绝对值、向上取整等。无构造函数,无法被初始化,只提供静态属性和方法。

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

1.2 构造函数

官方文档解释

无 :Math 对象无构造函数,无法被初始化,只提供静态属性和方法。

上面只说了问题的出现与对应的解决方式,如果有兴趣继续了解该函数的,可以继续往下读,首先来看下官方文档对此函数的解释。

1.3 静态属性

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

1.3.1 Math.E :常量e。返回自然对数的底数:2.7182818284590451.3.2 Math.PI :常量π。返回圆周率的值 :3.1415926535897931.4 静态方法

参数注释

1.4.1 Math.sin :正弦函数1.4.2 Math.cos :余弦函数1.4.3 Math.tan :正切函数1.4.4 Math.asin :反正弦函数1.4.5 Math.acos :反余弦函数1.4.6 Math.atan :反正切函数1.4.7 Math.abs :返回绝对值

data

参数:①value {Number | NumberStr} :数字或者纯数字的字符串。返回值:{Number} 返回参数的绝对值数字。若参数不为数字,返回NaN。示例:

以前用来生成签名的数据字符串。

复制代码 代码如下:h.abs; // => 123 :纯数字字符串Math.abs; // => 123Math.abs; // => 123Math.abs; // => 123Math.abs; // => NaN :非纯数字字符串

signature

1.4.8 Math.ceil : 对一个数向上取整,并不是四舍五入参数:①value {Number | NumberStr} :数字或者纯数字的字符串。返回值:{Number} 返回取整后的值。若参数不为数字,返回NaN。示例:复制代码 代码如下:Math.ceil; // => 3Math.ceil; // => 3 :2.3 向上取整返回 3Math.ceil; // => -2Math.ceil; // => -2Math.ceil; // => 3 :纯数字字符串Math.ceil; // => NaN :非纯数字字符串1.4.9 Math.floor :对一个数向下取整,并不是四舍五入参数:①value {Number | NumberStr} :数字或者纯数字的字符串。返回值:{Number} 返回取整后的值。若参数不为数字,返回NaN。示例:

原始二进制字符串,通过openssl_sign()或类似的函数生成。

复制代码 代码如下:Math.floor; // => 2Math.floor; // => 2Math.floor; // => -3 :-2.7 向下取整返回 -3Math.floor; // => -3Math.floor; // => 2 :纯数字字符串Math.floor; // => NaN :非纯数字字符串1.4.10 Math.max(value1,value2...valueN) :返回参数中最大的值参数:①value1,value2.....valueN {Number | NumberStr} :数字或者纯数字的字符串。返回值:{Number} 返回最大值。若一个参数不为数字,返回NaN。示例:复制代码 代码如下:Math.max; // => 5Math.max; // => 5Math.max; // => NaN 1.4.11 Math.min(value1,value2...valueN) :返回参数中最小的值参数:①value1,value2.....valueN {Number | NumberStr} :数字或者纯数字的字符串。返回值:{Number} 返回最大值。若一个参数不为数字,返回NaN。示例:复制代码 代码如下:Math.min; // => 1Math.min; // => 1Math.min; // => NaN1.4.12 Math.pow :返回x的y次方参数:①x {Number | NumberStr} :数字或者纯数字的字符串。②y {Number | NumberStr} :数字或者纯数字的字符串。返回值:{Number} 返回x的y次方。若一个参数不为数字,返回NaN。示例:

pub_key_id

复制代码 代码如下:Math.pow; // => 8 :2的3次方Math.pow; // => 9 :3的2次方Math.pow; // => 16 :4的2次方Math.pow; // => NaN1.4.13 Math.random() :返回一个伪随机数,大于0,小于1.0参数:无返回值:{Number} 返回一个伪随机数,大于0,小于1.0示例:

resource - 一个密钥, 通过 openssl_get_publickey() 函数返回。

复制代码 代码如下:Math.random(); // => 0.8982374747283757Math.random(); // => 0.39617531932890415Math.random(); // => 0.35413061641156673Math.random(); // => 0.0544410517904907461.4.14 Math.round : 四舍五入后取整参数:①value {Number | NumberStr} :数字或者纯数字的字符串。返回值:{Integer} 返回参数四舍五入后的整数。若参数不为数字,返回NaN。示例:复制代码 代码如下:Math.round; // => 3Math.round; // => 2Math.round; // => -3Math.round; // => -2 :-2.5四舍五入为 -2Math.round; // => -2Math.round; // => 3 :纯数字字符串Math.round; // => NaN :非纯数字字符串1.4.15 Math.sqrt :返回参数的平方根参数:①value {Number | NumberStr} :数字或者纯数字的字符串返回值:{Number} 返回参数的平方根示例:复制代码 代码如下:console.log; // => 3console.log; // => 4console.log; // => 5console.log; // => NaN

string - 一个 PEM 格式的密钥, 比如, “—–BEGIN PUBLIC KEY—– MIIBCgK…”

  1. Number 对象

signature_alg

2.1 介绍 Number 对象,是数字对象,包含js中的整数、浮点数等等。

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

2.2 定义复制代码 代码如下:var a = 1;var b = 1.1;

string - 由openssl_get_md_methods()函数返回的可用字符串,比如, “sha1WithRSAEncryption” 或者 “sha512”.官方文档给出的signature_alg参数可以为int或者string类型,int类型直接调用对应的枚举值,string则是openssl_get_md_methods函数返回的可用字符串,调用openssl_get_md_methods方法打印参数如下,而这些字符串也是对应加密方式的摘要信息,后文源码中可能会看的对函数调用稍微明白那么一丢丢。

2.3 静态属性2.3.1 Number.MAX_VALUE :表示JS中最大的数字,约为 1.79e+3082.3.2 Number.MIN_VALUE :表示JS中最小的数字,约为 5e-3242.3.3 Number.NaN :返回NaN,表示非数字值,与任意其他数字不等,也包括NaN本身。应使用Number.isNaN() 来进行判断。2.3.4 Number.NEGATIVE_INFINITY :返回 -Infinity ,表示负无穷。2.3.5 Number.POSITIVE_INFINITY :返回 Infinity ,表示正无穷。进行计算的值大于Number.MAX_VALUE就返回 Infinity 。2.4 静态方法2.4.1 Number.isInteger :判断参数是否为整数 参数:①value {Number} :数字返回值:{Boolean} 返回参数是否为整数 。纯整数的字符串也返回false。示例:复制代码 代码如下:Number.isInteger; // => trueNumber.isInteger; // => falseNumber.isInteger; // => false :纯整数的字符串也返回falseNumber.isInteger; // => falseNumber.isInteger; // => false :非字符串返回false2.4.2 Number.isNaN :判断参数是否为NaN参数:①value {Object} :任意类型返回值:{Boolean} 返回参数是否为NaN 。示例:复制代码 代码如下:Number.isNaN; // => trueNumber.isNaN; // => false :'NaN'字符串,并不为NaNNumber.isNaN; // => falseNumber.isNaN; // => false2.4.3 Number.parseFloat :把参数转换为浮点数参数:①value {Number | NumberStr} :数字或者纯数字的字符串返回值:{Integer | Float} 返回整数或浮点数数值示例:复制代码 代码如下:Number.parseFloat; // => 1 :整数还是返回整数Number.parseFloat; // => 1.1Number.parseFloat; // => 1 :字符串前面为数字的,只返回数字Number.parseFloat; // => 1.1Number.parseFloat; // => NaN :非数字开头,返回NaNNumber.parseFloat; // => NaN2.4.4 Number.parseInt :把参数转换为整数参数:①value {Number | NumberStr} :数字或者纯数字的字符串返回值:{Integer} 返回整数数值示例:复制代码 代码如下:Number.parseInt; // => 1Number.parseInt; // => 1 :浮点数返回整数Number.parseInt; // => 1 :字符串前面为数字的,只返回数字Number.parseInt; // => 1Number.parseInt; // => NaN :非数字开头,返回NaNNumber.parseInt; // => NaN

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)

2.5 实例方法2.5.1 toExponential :将一个数字转为指数类型,参数表示小数点后的位数参数:①value {Number} :表示小数点后的位数返回值:{String} 返回转换后的指数类型字符串示例:复制代码 代码如下:.toExponential; // => 1.23e+8 :小数点2位.toExponential; // => 1.23457e+8 :小数点5位.toExponential; // => 1.2345678900e+8 :小数点10位,不足位数用0补位2.5.2 toFixed :将一个数字转换为指定小数位数的字符串。不传入参数,就是没小数位。返回值为四舍五入参数:①value {Number} :表示小数点后的位数返回值:{String} 返回转换后的字符串;不够小数位以0填充;返回值为四舍五入后的值示例:复制代码 代码如下:console.log; // => 1.00console.log; // => 1.20 :不足位数,以0补位console.log; // => 1.28 :进行了四舍五入2.5.3 toString() :使用指定的进制,将一个数字转换为字符串。不传入参数,默认为十进制。参数:①value {Number} :表示进制数,取值范围:2到36返回值:{String} 转换后进制的字符串示例:复制代码 代码如下:; // => 10 :默认为十进制; // => 1010 :二进制; // => 10 :十进制; // => a :十六进制

由此也可看出函数是兼容两种模式的,但是为什么php版本会有兼容问题么?在openssl库版本是一致的情况下,接下来的原因应该只遗留在php扩展的问题上。那下面来看看对应的源码去发现问题出现在哪吧。

2.6.1 浮点数的加减乘除异常说明:Js中的2个浮点数进行加减乘除运算,会返回异常的数值,如:0.2+0.7,返回0.899999999999。可以使用toFixed()方法,指定小数位。示例:复制代码 代码如下:console.log; // => 0.8999999999999999console.log; // => 0.19999999999999996console.log; // => 30.299999999999997// 使用toFixed()方法console.log.toFixed; // => 0.90console.log.toFixed; // => 0.20 console.log.toFixed; // => 30.302.6.2 减法运算说明:Js中进行减法运算时,会先把前后的值转换为数值再进行运算。若转换失败,返回NaN。示例:复制代码 代码如下:console.log; // => 1 :纯数字字符串减去0,可以快速转换为Nubmer对象console.log ); // => 1.00 :快速转换为Nubmer对象后调用实例方法console.log; // => NaN :一方无法转换为Nubmer对象

openssl_verify函数源码

openssl_verify源码中有这样一段,如果参数method为string类型的时候,调用openssl库的EVP_get_digestbyname方法,在网上查看了下此方法的作用,主要是根据摘要信息返回EVP_MD结构,而EVP_get_digestbyname方法由于是openssl库源代码并且对C语言知之甚少,熊某就没去查看,只是了解php代码调用背后的一些处理逻辑,有兴趣的可以看看openssl库的代码实现。

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

一开始本人以为php5.3版本会是method参数类型的限制,一看源代码才发现,openssl_verify函数的实现逻辑是一致的,都是检测method参数类型,那么问题就不出现在参数类型上,然后我查看了参数为long类型是所调用的php_openssl_get_evp_md_from_algo函数,果然发现了问题所在。源码如下:

static EVP_MD * php_openssl_get_evp_md_from_algo { /* {{{ */ EVP_MD *mdtype; switch  { case OPENSSL_ALGO_SHA1: mdtype = ; break; case OPENSSL_ALGO_MD5: mdtype = ; break; case OPENSSL_ALGO_MD4: mdtype = ; break;#ifdef HAVE_OPENSSL_MD2_H case OPENSSL_ALGO_MD2: mdtype = ; break;#endif case OPENSSL_ALGO_DSS1: mdtype = ; break; default: return NULL; break; } return mdtype;}

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

由上面源代码可以很清晰的发现问题所在,随着php版本的升级,其所在的openssl扩展对应的调用条件也增加了很多,最后导致上述问题的源码也只是switch…case少了几个条件,在此也希望大家发现问题的时候,可以先去解决问题,然后有兴趣的话可以去查看源代码分析下问题所导致的原因。

本文由澳门新葡8455手机版发布于摄影欣赏,转载请注明出处:规范影室闪光灯

TAG标签:
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。