#前回の記事では、対称暗号化と非対称暗号化に関する関連する理論的知識を学び、OpenSSL を使用して対称暗号化操作を実行する方法についても学びました。今日はさらに一歩進んで、OpenSSL で非対称暗号化がどのように実装されるかを学びます。
秘密キーの生成
これまでの学習を通じて、非対称暗号化には公開キーと秘密キーがそれぞれ必要であることがわかりました。まず、私たちの側に保存される鍵である秘密鍵を生成しましょう。秘密キーはいかなる場合でも他人に渡すことはできないことに注意してください。
$config = array( "private_key_bits" => 4096, // 指定应该使用多少位来生成私钥 ); $res = openssl_pkey_new($config); // 根据配置信息生成私钥 openssl_pkey_export($res, $privateKey); // 将一个密钥的可输出表示转换为字符串 var_dump($privateKey); // -----BEGIN PRIVATE KEY----- // MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDFMLW+9t3fNX4C // YBuV0ILSyPAdSYVXtE4CLv32OvNk9yQZgF2nL/ZuIbBGRcYo2Hf5B31doGrAFDGu // NoTR+WA7CBjKROFr/+yValsMFIeiKNtttWMkmBciysDJoEoyd6wjDD+kcHQdoJVo // …… // -----END PRIVATE KEY-----
非常に単純な関数 openssl_pkey_new() は、構成可能なオプションのパラメーターであるパラメーターを受け取ります。生成された結果は秘密キー ハンドルですが、これは直接読み取ることができないため、openssl_pkey_export() を使用して出力文字列を抽出します。
コメントの内容は当社で生成した秘密鍵情報ですが、一般に秘密鍵情報は比較的容量が大きいため、以下の内容は省略させていただきます。
公開キーの抽出
次のステップでは、公開キーを生成します。実際、公開キーは秘密キーから抽出されます。したがって、暗号化と復号化を使用する場合、秘密キーまたは公開キーを使用して相互に操作できます。
$publicKey = openssl_pkey_get_details($res); // 抽取公钥信息 var_dump($publicKey); // array(4) { // ["bits"]=> // int(4096) // ["key"]=> // string(800) "-----BEGIN PUBLIC KEY----- // MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtOIImDdS0W0vAr5Ra1+E // hR2AJwQQwxntYKgTku8EmJRBX2vU+x8th8W8SnoGiVM/sOItG0HIe4Egf1UxoZHt // gI6r+jpAp7JbTN0sD/VTPDE09F21+hFGjIVBqrkcLPjuEbf7+tjmgAx8cG8WLGId // G8Hsub70kRANKJe1bCXIBUggRFk0sQGllxA/hxiG5wANqHTrdpJgJba+ahSi2+4H // UWnyCV1O3AaPyz6a12HNUsG4Eio/tWv/hOB9POt6nAqwPHuIbhp56i5bv1ijMJZM // jwRen5f/kwdZ01Ig2fi0uBoTR2y/EEaus7xBYpF/gGzZ/uM7cNUXcDyG5YluM/4R // MEv4msPMVGB72izItED+C6Cqftxl98iBFRDc+PISFbRSgOU/HsuBhKkM5SYzyi3I // Ypaej25++qLPqcA+EDr3JNDhNZ0GOhofCRtPq4dsr7iLLLRnZ0TnhIYe9wAbmO49 // uthABNBkM54bG+omOfY4Bkn5n39CKpELbhIiXgOd+lA684XUS/2Aw3Dvelc9Gbag // oIFvb/wljPYsd0Zmd64CXBpTWbfwXC8K4vCKvFLjytcz2Yp4T6fVjbLT5RA6u8su // E0WwE4QTFNKhnM5OvfiMN+NMc3Y/esVfcin3eyvotdz4N6Tt45dkybkf6aQE3Scg // E/JBLIEEA+gjGTveY4cNUiECAwEAAQ== // -----END PUBLIC KEY----- // " // ["rsa"]=> // …… $publicKey = $publicKey['key'];
openssl_pkey_get_details() を使用して抽出されたコンテンツには、多くのコンテンツが含まれています。ただし、主に必要なのは、キーの下にある公開キーです。
公開鍵と秘密鍵の内容を詳しく見てみましょう。申請した HTTPS 証明書の公開鍵と秘密鍵の内容は同じですか、類似していますか?システムで openssl を使用しているものと同じですか? コマンド ラインで生成されたキー証明書はローカルのものと同じです。それら自体は同じものですが、異なるシナリオでは異なる方法で適用されます。 HTTPS 証明書には非対称暗号化キーに加えて CA 情報も含まれており、CA が通過しない場合、ブラウザは証明書が無効であるとみなしてしまうため、生成した証明書を HTTPS 証明書として使用することはできません。独自に生成されたものは通常、SSH パスワード不要のログインまたは GitHub パスワード不要のコード ウェアハウス操作に使用されます。
データの暗号化と復号化
公開キーと秘密キーが生成されました。次に、最も重要な暗号化と復号化の操作を実行します。
$data = '测试非对称加密'; // 公钥加密数据 openssl_public_encrypt($data, $encrypted, $publicKey); var_dump($encrypted); // string(512) // 私钥解密数据 openssl_private_decrypt($encrypted, $decrypted, $privateKey); var_dump($decrypted); // string(21) "测试非对称加密"
ここでは、最も標準的な公開キー暗号化と秘密キー復号化をテストに使用します。 OpenSSL は、公開キーの暗号化と復号化、および秘密キーの暗号化と復号化の機能を提供します。
前回の記事の図のように、相手はこちらの公開鍵を取得してデータを暗号化して送信し、こちらは自分の秘密鍵でデータを復号して原文を取得します。また、相手の公開鍵を取得し、返されたデータを暗号化して相手に送信すると、相手は独自の秘密鍵を使用して復号化して、渡した元のデータを取得することもできます。
HTTPS は CA が発行した証明書を通じて公開キーを取得します。ブラウザはリクエスト データを暗号化してサーバーに送信します。サーバーも同じ原理を使用して暗号文データをブラウザ クライアントに送信します。したがって、データ送信の際には、HTTPS を使用した送信の方が安全であり、たとえ傍受されたとしても、相手は証明書によって提供された暗号を解読するための鍵を持っていません。これが、すべてのアプリとミニプログラム アプリケーションで HTTPS の使用が必要になる理由です。もちろん、Web サイト開発を行う場合は、HTTPS を使用するのが最善です。Baidu でさえ、HTTPS を含めるために対応する調整を行っています。
署名と検証
次に、署名の概念について触れます。 2 つの端が通信するとき、現在送信されているデータがもう一方の端から送信されたものである必要があることをどのようにして知ることができますか? ハッカーがデータを改ざんしたことがありますか?これは署名メカニズムを通じて検証できます。
// 利用私钥生成签名 openssl_sign($data, $signature, $privateKey, OPENSSL_ALGO_SHA256); var_dump($signature); // 公钥验证签名 $r = openssl_verify($data, $signature, $publicKey, OPENSSL_ALGO_SHA256); var_dump($r); // int(1)
openssl_sign() を使用して元のデータの秘密キー署名を生成し、openssl_verify() を使用してデータ署名が公開キーを通じて一貫しているかどうかを検証できます。
使用すると、送信者は独自の秘密キーを介して署名を生成します。署名の内容は文字化けするため、base64_encode() して、暗号化されたデータとともに受信者に渡すことができます。受信者は公開鍵を使用し、署名内容に基づいて元のデータが改ざんされていないかどうかを検証します。
// 发送方签名 $resquestSign = base64_encode($signature); // 假设通过网络请求发送了数据 // …… // 接收到获得签名及原始数据 // $signature = $_POST['sign']; // openssl_private_decrypt($_POST['data'], $data, $privateKey); $responseSign = base64_decode($signature); // 验证数据有没有被篡改 $r = openssl_verify($data, $signature, $publicKey, OPENSSL_ALGO_SHA256); var_dump($r); // int(1) // 假设被篡改 $data = '我被修改了'; $r = openssl_verify($data, $signature, $publicKey, OPENSSL_ALGO_SHA256); var_dump($r); // 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
推荐学习:php视频教程