上篇文章,我们了解了关于对称和非对称加密的一些相关的理论知识,也学习了使用 OpenSSL 来进行对称加密的操作。今天,我们就更进一步,学习 OpenSSL 中的非对称加密是如何实现的。

生成私钥

通过之前的学习,我们知道非对称加密是分别需要一个公钥和一个私钥的。我们就先来生成一个私钥,也就是存放在我们这一端一个密钥。请记住,在任何时候,私钥都是不能给别人的哦!

  1. $config = array(
  2. "private_key_bits" => 4096, // 指定应该使用多少位来生成私钥
  3. );
  4. $res = openssl_pkey_new($config); // 根据配置信息生成私钥
  5. openssl_pkey_export($res, $privateKey); // 将一个密钥的可输出表示转换为字符串
  6. var_dump($privateKey);
  7. // -----BEGIN PRIVATE KEY-----
  8. // MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDFMLW+9t3fNX4C
  9. // YBuV0ILSyPAdSYVXtE4CLv32OvNk9yQZgF2nL/ZuIbBGRcYo2Hf5B31doGrAFDGu
  10. // NoTR+WA7CBjKROFr/+yValsMFIeiKNtttWMkmBciysDJoEoyd6wjDD+kcHQdoJVo
  11. // ……
  12. // -----END PRIVATE KEY-----

非常简单的一个函数 openssl_pkey_new() ,它接收一个参数,这个参数是可配置项并且是可选参数。生成的结果是一个私钥句柄,不是我们能直接读取的内容,所以我们再使用 openssl_pkey_export() 来提取可输出的字符串。

注释中的内容就是我们生成的私钥信息了,私钥信息一般会相对多些,所以省略了后面的内容。

抽取公钥

接下来就是生成公钥了,其实,公钥是从私钥中抽取出来的。所以我们使用进行加解密的时候,都可以使用私钥或者公钥互相操作。

  1. $publicKey = openssl_pkey_get_details($res); // 抽取公钥信息
  2. var_dump($publicKey);
  3. // array(4) {
  4. // ["bits"]=>
  5. // int(4096)
  6. // ["key"]=>
  7. // string(800) "-----BEGIN PUBLIC KEY-----
  8. // MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtOIImDdS0W0vAr5Ra1+E
  9. // hR2AJwQQwxntYKgTku8EmJRBX2vU+x8th8W8SnoGiVM/sOItG0HIe4Egf1UxoZHt
  10. // gI6r+jpAp7JbTN0sD/VTPDE09F21+hFGjIVBqrkcLPjuEbf7+tjmgAx8cG8WLGId
  11. // G8Hsub70kRANKJe1bCXIBUggRFk0sQGllxA/hxiG5wANqHTrdpJgJba+ahSi2+4H
  12. // UWnyCV1O3AaPyz6a12HNUsG4Eio/tWv/hOB9POt6nAqwPHuIbhp56i5bv1ijMJZM
  13. // jwRen5f/kwdZ01Ig2fi0uBoTR2y/EEaus7xBYpF/gGzZ/uM7cNUXcDyG5YluM/4R
  14. // MEv4msPMVGB72izItED+C6Cqftxl98iBFRDc+PISFbRSgOU/HsuBhKkM5SYzyi3I
  15. // Ypaej25++qLPqcA+EDr3JNDhNZ0GOhofCRtPq4dsr7iLLLRnZ0TnhIYe9wAbmO49
  16. // uthABNBkM54bG+omOfY4Bkn5n39CKpELbhIiXgOd+lA684XUS/2Aw3Dvelc9Gbag
  17. // oIFvb/wljPYsd0Zmd64CXBpTWbfwXC8K4vCKvFLjytcz2Yp4T6fVjbLT5RA6u8su
  18. // E0WwE4QTFNKhnM5OvfiMN+NMc3Y/esVfcin3eyvotdz4N6Tt45dkybkf6aQE3Scg
  19. // E/JBLIEEA+gjGTveY4cNUiECAwEAAQ==
  20. // -----END PUBLIC KEY-----
  21. // "
  22. // ["rsa"]=>
  23. // ……
  24. $publicKey = $publicKey['key'];

使用 openssl_pkey_get_details() 抽取出来的内容包含很多内容。不过我们所需要的最主要的内容就是 key 下面的这个公钥。

大家再回过头来好好看一下公钥和私钥的内容,是不是和我们去申请的 HTTPS 证书中的公私钥内容长得一样,而且也和我们自己在系统中使用 openssl 命令行生成的本机的密钥证书一样。它们本身就是一样的东西啦,只是在不同的场景应用的不同而已。HTTPS 证书除了非对称加密的密钥之外,还包含有 CA 信息,如果 CA 不通过,浏览器也会认为证书是无效的,因此,我们使用自己生成的证书来充当 HTTPS 证书是不可以的。而本身生成的一般会用在 SSH 免密登录上,或者是 GitHub 的免密代码仓库操作上。

加密解密数据

好了,公钥和私钥都生成完成了,那么我们就要进行最重要的加密和解密操作了。

  1. $data = '测试非对称加密';
  2. // 公钥加密数据
  3. openssl_public_encrypt($data, $encrypted, $publicKey);
  4. var_dump($encrypted);
  5. // string(512) "��E��2��~��\d����q�O�=(��Y���3L����0�,�J����s�V��V߬G~'�20���@��6�d�����#Z]�.��<Z��8G�����-ʝ�M�0](2��+$�*����\e�7ҕʴ��|SUw�#rFb�8"�s4K�B�Y�'�\S���~!<�"���!U��S(���S ��?e�֜r��/���c��L�YL�'ŖE*S��[�J�"�n��`(ʿoF$�|kC�*j_y�E�D�O����H5���6�t�TY����b5l^)�`�v�>�1��a��r�̹�D��������@�S�>�t|���匓�z~K�,���y��Gܬ��
  6. // yXZ�L#��c `rj睅,nX���@{7�:�qy�ʲnv�o§�@�@,�n&���I�~ǧ�z6���oe!8,T�����;җ�6�J@A��f����S]��!����2�b��+Oګ��o�<�
  7. // ����-�+et��})�KG��$���,�Z|�"
  8. // 私钥解密数据
  9. openssl_private_decrypt($encrypted, $decrypted, $privateKey);
  10. var_dump($decrypted);
  11. // string(21) "测试非对称加密"

在这里,我们使用的就是最标准的公钥加密,私钥解密来进行的测试。其实反过来也是可以的,OpenSSL 分别都为我们提供了公钥的加解密和私钥的加解密函数。

就像上篇文章的图示那样,对方获得我们的公钥,然后加密数据传输过来,我们通过自己的私钥解密数据获得原文。而我方也可以获得对方的公钥,并将返回的数据加密后传输给对方,然后对方使用自己的私钥进行解密获得我们传递给它的原文数据。

而 HTTPS 是通过 CA 颁发的证书来获取公钥的,浏览器通过公钥加密请求数据传输给服务器,服务器也是通过相同的原理来向浏览器客户端发送密文数据。因此,在数据传输过程中,使用 HTTPS 的传输会更加地安全,即使被截获了,对方也没有证书提供的密钥来进行解密。这就是现在所有 App 和 小程序 应用都要求使用 HTTPS 的原因,当然,我们如果做网站开发也最好使用 HTTPS ,就连百度对 HTTPS 的收录也有相应的调整。

签名及验证

接下来我们再接触一个签名的概念。当两端进行通信时,我们怎么知道当前传输过来的数据一定是对端发送过来的的呢,中间有没有黑客进行了篡改呢?这个就可以通过签名机制来进行验证。

  1. // 利用私钥生成签名
  2. openssl_sign($data, $signature, $privateKey, OPENSSL_ALGO_SHA256);
  3. var_dump($signature);
  4. // ��<�~�k�٭N����M�тq��;��h�dŬ�Ğ�m�3�nj��/i���U�_�E2z���>B�N�WM!TN�c�F�/��,5�|���%��c~O)"
  5. // �� >��)y�fn��q��}
  6. // �`
  7. // �z��{��_D�s`�����|y�,g>R�D��%�
  8. // �gͯ0�@Λ|��|z}���bZI2,����~Q_���I�LW~���G&���f�|eq�s�D���L���bC'D��~8:�Z����\�9]C�Kd~F96�S� 0��y>�(T��S}��1�謃T
  9. // �!��!!�Lj�<�ǺfM�o7�3��������� 8ZR<Vya4����V��Wט����L�QZbv��7?�v`}��?v ǿ�0`�OF��F��@�$b�PBI�o\�v���D���"
  10. // 公钥验证签名
  11. $r = openssl_verify($data, $signature, $publicKey, OPENSSL_ALGO_SHA256);
  12. var_dump($r);
  13. // int(1)

我们通过 openssl_sign() 来生成一个对原始数据的私钥签名,然后就可以使用 openssl_verify() 通过公钥验证数据签名是否一致。

在使用的时候,发送方通过自己的私钥生成签名,由于签名内容是乱码的,我们可以将它 base64_encode() 一下,然后连同加密数据一起传递给接收方。然后接收方使用公钥并根据签名内容来验证原文数据是否被篡改过。

  1. // 发送方签名
  2. $resquestSign = base64_encode($signature);
  3. // 假设通过网络请求发送了数据
  4. // ……
  5. // 接收到获得签名及原始数据
  6. // $signature = $_POST['sign'];
  7. // openssl_private_decrypt($_POST['data'], $data, $privateKey);
  8. $responseSign = base64_decode($signature);
  9. // 验证数据有没有被篡改
  10. $r = openssl_verify($data, $signature, $publicKey, OPENSSL_ALGO_SHA256);
  11. var_dump($r);
  12. // int(1)
  13. // 假设被篡改
  14. $data = '我被修改了';
  15. $r = openssl_verify($data, $signature, $publicKey, OPENSSL_ALGO_SHA256);
  16. var_dump($r);
  17. // int(0)

总结

今天的内容是不是感觉比对称加密复杂了许多。特别新引入的签名的这个概念,其实很多证书相关的内容都会和数据签名有关系。也就是说,看似简单的一个 HTTPS ,其实浏览器和服务端的 openssl 帮我们做了很多事情,远不止你去 CA 申请一套证书然后在 Nginx 配好那么简单。那么,接下来,我们将要学习的就是生成证书相关的内容了,系好安全带,车还要继续飙。

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202007/source/PHP%E7%9A%84OpenSSL%E5%8A%A0%E5%AF%86%E6%89%A9%E5%B1%95%E5%AD%A6%E4%B9%A0%EF%BC%88%E4%BA%8C%EF%BC%89%EF%BC%9A%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86.php

参考文档:

https://www.php.net/manual/zh/function.openssl-pkey-new.php

https://www.php.net/manual/zh/function.openssl-pkey-get-details.php

https://www.php.net/manual/zh/function.openssl-pkey-export.php

https://www.php.net/manual/zh/function.openssl-public-encrypt.php

https://www.php.net/manual/zh/function.openssl-private-decrypt.php

https://www.php.net/manual/zh/function.openssl-sign.php

https://www.php.net/manual/zh/function.openssl-verify.php

关注公众号:【硬核项目经理】获取最新文章

添加微信/QQ好友:【xiaoyuezigonggong/149844827】免费得PHP、项目管理学习资料

知乎、公众号、抖音、头条搜索【硬核项目经理】

B站ID:482780532

PHP的OpenSSL加密扩展学习(二):非对称加密的更多相关文章

  1. PHP的OpenSSL加密扩展学习(一):对称加密

    我们已经学过不少 PHP 中加密扩展相关的内容了.而今天开始,我们要学习的则是重点中的重点,那就是 OpenSSL 加密扩展的使用.为什么说它是重点中的重点呢?一是 OpenSSL 是目前 PHP 甚 ...

  2. 加密解密知识 php非对称加密

    function test1(){ $config = array( "digest_alg" => "sha1", "private_key_ ...

  3. PHP中使用OpenSSL生成RSA公钥私钥及进行加密解密示例(非对称加密)

    php服务端与客户端交互.提供开放api时,通常需要对敏感的部分api数据传输进行数据加密,这时候rsa非对称加密就能派上用处了,下面通过一个例子来说明如何用php来实现数据的加密解密 先了解一下关于 ...

  4. 常见三种加密(MD5、非对称加密,对称加密)

    转载. https://blog.csdn.net/SSY_1992/article/details/79094556 任何应用的开发中安全都是重中之重,在信息交互异常活跃的现在,信息加密技术显得尤为 ...

  5. 使用java实现对称加密解密(AES),非对称加密解密(RSA)

    对称加密:双方采用同样的秘钥进行加密和解密.特点是速度快,但是安全性没有非对称加密高 非对称加密:接收方生成的公有秘钥公布给发送方,发送方使用该公有秘钥加密之后,发送给接收方,然后接收方使用私有秘钥解 ...

  6. PHP的OpenSSL加密扩展学习(三):证书操作

    关于对称和非对称的加密操作,我们已经学习完两篇文章的内容了,接下来,我们就继续学习关于证书的生成. 生成 CSR 证书签名请求 CSR 是用于生成证书的签名请求,在 CSR 中,我们需要一些 dn 信 ...

  7. PHP的openssl加密扩展使用小结

    h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-child, body>h ...

  8. PHP openssl加密扩展使用总结

    1.检查服务器是否已安装了openssl组件,没有则先安装好 openssl version [-a] 2.对称加密 查询openssl支持的对称加密算法 openssl_get_cipher_met ...

  9. openssl 下的对称加密和非对称加密

    对称加密: 在加密和解密过程中使用相同的密钥, 或是两个可以简单地相互推算的密钥的加密算法. 非对称加密: 也称为公开加密, 它需要一个密钥对, 一个是公钥, 一个是私钥, 一个负责加密, 一个负责解 ...

随机推荐

  1. linux虚拟机环境快速搭建redis5.x版本的主从集群总结

    文/朱季谦 我在阿里云服务器上曾参与过公司redis集群的搭建,但时间久了,都快忘记当时的搭建过程了,故而决定在虚拟机centOS 7的环境,自行搭建一套redis5.x版本的集群,该版本集群的搭建比 ...

  2. PTA 朋友圈 (25 分) 代码详解 (并查集)

    1.题目要求: 某学校有N个学生,形成M个俱乐部.每个俱乐部里的学生有着一定相似的兴趣爱好,形成一个朋友圈.一个学生可以同时属于若干个不同的俱乐部.根据"我的朋友的朋友也是我的朋友" ...

  3. Java EE-下载安装eclipse并设置环境变量的步骤

    1.下载eclipse: 官网:https://www.eclipse.org/downloads/ (1)点击链接后显示如图 (2)点击Download Packages 下载安装包,不要点击&qu ...

  4. Java GC【笔记】

    Java GC(垃圾回收机制) (PS:篇幅很长的,样式都会重新整一下,比如使用二级) 首先我们得知道,一个对象被判定为垃圾的标准是什么? 对于Java对象来说,当不被其他的对象引用的时候,就可以看作 ...

  5. Java JVM【笔记】

    Java JVM[笔记] Java的平台无关性是如何实现的? Java源码首先被编译成字节码,再由不同的平台的JVM进行解析,Java语言在不同的平台上运行时不需要进行重新编译,Java虚拟机在执行字 ...

  6. efcore分表下"完美"实现

    ShardingCore 如何呈现"完美"分表 这篇文章是我针对efcore的分表的简单介绍,如果您有以下需求那么可以自己选择是否使用本框架,本框架将一直持续更新下去,并且免费开源 ...

  7. Linux下MySQL主从复制(Binlog)的部署过程

    什么是 MySQL 的主从复制 Mysql内建的复制功能是构建大型高性能应用程序的基础, 将Mysql数据分布到多个系统上,这种分布机制是通过将Mysql某一台主机数据复制到其它主机(slaves)上 ...

  8. Ratel:一直站在Android逆向巅峰的平头哥

    本文来源:带动行业内卷,渣总义不容辞 字越少事儿越大,请关注github(可以点击阅读原文): https://github.com/virjarRatel 平头哥(ratel)是一个Android逆 ...

  9. .NET Core:在ASP.NET Core WebApi中使用Cookie

    一.Cookie的作用 Cookie通常用来存储有关用户信息的一条数据,可以用来标识登录用户,Cookie存储在客户端的浏览器上.在大多数浏览器中,每个Cookie都存储为一个小文件.Cookie表示 ...

  10. 菜鸟攻略–C语言多文件编程初探(二):使用 gcc 手动编译多文件 C 程序

    step1:下载安装 Dev-C++ 已经安装了 Dev-C++ 或系统中的可以跳过这步.去官网下载 Dev-C++.我昨天下载,发现有点慢,所以我把安装文件放到百度网盘了,供大家下载,下载链接为:h ...