(本文阅读预计10分钟)
前言:
最近公司在对接第四方采宝服务商,用于聚合门店支付。之前对接微信支付宝都有sdk下载,直接调用服务即可,很多加密中间知识有盲区。
确实,任何时候都得注重基础。
想起了Swoole作者韩天峰曾提及:
“不重视基础。就好比练武功,只求速成,不修炼内功和心法,只练各种招式,这样能高到哪里去?”
(https://blog.csdn.net/ty_hf/article/details/74942935)
这回就把知识的不扎实,翻出来再晒晒理理吧,是学习,也是潜下心来,故有此文。
目录
知其所以然,很好的一篇图文文章,传送门:数字签名是什么?
让人瞌睡的什么原理算法这里就不提了
百度百科粘贴的一段话:
RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。
当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。
来源:蚂蚁金服在原来RSA的SHA1WithRSA签名算法的基础上,新增了支持SHA256WithRSA的签名算法。便产生的RSA2
优点:该算法在摘要算法上比SHA1WithRSA有更强的安全能力。
换句话说,RSA2这个名词来自于蚂蚁金服,并没有出现新的技术,它只是RSA的升级版,更安全。
(忽然想起以前有种md6加密算法,本质是md5了两次)
开放平台签名算法名称 |
标准签名算法名称 |
备注 |
RSA2 |
SHA256WithRSA |
强制要求RSA密钥的长度至少为2048 |
RSA |
SHA1WithRSA |
对RSA密钥的长度不限制,推荐使用2048位以上 |
在php官方扩展代码openssl.php中,截取片段如下:
我们在使用rsa加密时,通过openssl_sign实现
if ("RSA2" == $signType) {
openssl_sign($data, $sign, $res, OPENSSL_ALGO_SHA256);//RSA2加密
} else {
openssl_sign($data, $sign, $res,OPENSSL_ALGO_SHA1);//RSA加密
}
不难看出,RSA与RSA2的切换时通过第4个参数实现
/**
* Used as default algorithm by openssl_sign and
* openssl_verify.
* @link https://php.net/manual/en/openssl.constants.php
*/
define ('OPENSSL_ALGO_SHA1', 1);
define ('OPENSSL_ALGO_MD5', 2);
define ('OPENSSL_ALGO_MD4', 3);
define ('OPENSSL_ALGO_MD2', 4);
define ('OPENSSL_ALGO_DSS1', 5);
define ('OPENSSL_ALGO_SHA224', 6);
define ('OPENSSL_ALGO_SHA256', 7);
define ('OPENSSL_ALGO_SHA384', 8);
define ('OPENSSL_ALGO_SHA512', 9);
define ('OPENSSL_ALGO_RMD160', 10);
加密类型有三种:对称加密,非对称加密和其他
a.定义:加密密钥和解密密钥是相同的
b.问题:泄漏密钥就意味着任何人都可以对他们发送或接收的消息解密,所以密钥的保密性对通信的安全性至关重要。
c.举例:DES,AES等
a.定义:有两种密钥,一种是公共密钥(正如其名,这是一个可以公开的密钥值),一种是私人密钥(对外保密只有自己知道)
(两种密钥可以互相加解密,公钥加密的信息,只有我们的唯一的私钥可以解密,反之亦如此)
b.场景:
1).公钥加密信息,私钥解开;//常规数据加密,比如微信支付宝传输过程中
2).私钥加密信息,公钥解开;//常用于数据验签,
3).双方公钥加密,在特定排序下的数据加密后做键值对比;//同样用于验签作用,【这也是我们本次使用的方法】
c.举例:RSA、DSA等
有些同学可能会问,常用的md5、hash算法(sha1、sha256、sha512、sha1024等)怎么没被提及,
其实准确的说,md5和hash算法不能算是加密算法,它们都属于信息摘要算法,可以为不同的信息生成独一无二的信息摘要,而它们都属于不可逆算法,
1.php报错,公钥不可用
key parameter is not a valid public key error in openssl_public_encrypt()
原因是因为证书格式不正确,RSA单独签名方法未做字符串处理
需要把密钥由一串变成每行64位,
解决:
$public_key = "-----BEGIN PUBLIC KEY-----\n" .
wordwrap($public_key_content, 64, "\n", true) .
"\n-----END PUBLIC KEY-----";
2. 获取加密值时,openssl_pkey_get_public返回false
解决:在rsa加密时,被加密的明文长度最大为公钥长度-11,比如数据长度300,那么公钥长度必须大于311,否则失败返回false
3.rsa2的使用函数
// 4. 获取rsa2的密钥
$public_key_c = Env::get('root_path') . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'caibao_pem' . DIRECTORY_SEPARATOR . 'rsa_public_key.pem';
$public_key_content = file_get_contents($public_key_c);
$public_key = "-----BEGIN PUBLIC KEY-----\n" .
wordwrap($public_key_content, 64, "\n", true) .
"\n-----END PUBLIC KEY-----";
$res = openssl_get_publickey($public_key);
//对比两种签名,相同返回返回true ,不同返回false
$result = (openssl_verify($str, base64_decode($sign), $res, OPENSSL_ALGO_SHA256)===1);
openssl_free_key($res);
1.密码加密最好md5加盐salt,
2.尽量减少md5等摘要唯一不可逆加密算法,容易被攻破,愿不愿意的问题
支付宝:https://docs.open.alipay.com/291/105974
现代 PHP 中的密码安全性:https://www.ibm.com/developerworks/cn/web/wa-php-renewed_2/