php RSA加解密
<p><span style="font-size: 18px"><strong>相关介绍</strong></span></p><p><span style="font-size: 16px">RSA算法属于非对称加密算法,非对称加密算法需要两个秘钥:公开密钥(publickey)和私有秘钥(privatekey).公开密钥和私有秘钥是一对,</span></p>
<p><span style="color: rgba(255, 0, 0, 1); font-size: 16px">如果公开密钥对数据进行加密,只有用对应的私有秘钥才能解密;</span></p>
<p><span style="color: rgba(255, 0, 0, 1); font-size: 16px">如果私有秘钥对数据进行加密那么只有用对应的公开密钥才能解密.</span></p>
<p><span style="font-size: 16px">因为加密解密使用的是两个不同的秘钥,所以这种算法叫做非对称加密算法.简单的说就是公钥加密私钥解密,私钥加密公钥解密.</span></p>
<p><span style="font-size: 18px"><strong>需要注意的地方</strong></span></p>
<p><span style="font-size: 16px"><strong>1.</strong>RSA 加密或签名后的结果是不可读的二进制,使用时经常会转为 BASE64 码再传输</span></p>
<p><span style="font-size: 16px"><strong>2.</strong>RSA 加密时,对要加密数据的大小有限制,最大不大于密钥长度。例如在使用 1024 bit 的密钥时(秘钥生成可以自行百度),最大可以加密 1024/8=128 Bytes 的数据。数据大于 128 Bytes 时,需要对数据进行分组加密(如果数据超限,加解密时会失败,openssl 函数会返回 false),分组加密后的加密串拼接成一个字符串后发送给客户端。</span></p>
<p><span style="font-size: 16px">为了保证每次加密的结果都不同,RSA 加密时会在待加密数据后拼接一个随机字符串,再进行加密。不同的填充方式 Padding 表示这个字符串的不同长度,在对超限数据进行分组后,会按照这个 Padding 指定的长度填入随机字符串。例如如果 Padding 填充方式使用默认的 OPENSSL_PKCS1_PADDING(需要占用 11 个字节用于填充),那么明文长度最多只能就是 128-11=117 Bytes。</span></p>
<p><span style="font-size: 16px">接收方解密时也需要分组。将加密后的原始二进制数据(对于经过 BASE64 的数据,需要解码),每 128 Bytes 分为一组,然后再进行解密。解密后,根据 Padding 的长度丢弃随机字符串,把得到的原字符串拼接起来,就得到原始报文。</span></p>
<p><span style="font-size: 16px"><strong>3.</strong>openssl_public_encrypt函数 php的默认填充和无填充是有区别的,如果只是php和php对接则不需要关注这个问题,如果是php跟c或java,需要选择无填充然后自行加入填充</span></p>
<p><span style="font-size: 16px"><strong>4.</strong>需要将php的openssl模块打开或安装(win上是打开,linux上是安装,具体自行百度)</span></p>
<p><strong>为了方便我这里提供一组1024位的公私钥签名:</strong></p>
<p><em> </em></p>
<p>/*********************测试公钥*******************************<br>-----BEGIN PUBLIC KEY-----<br>MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmkANmC849IOntYQQdSgLvMMGm<br>8V/u838ATHaoZwvweoYyd+/7Wx+bx5bdktJb46YbqS1vz3VRdXsyJIWhpNcmtKhY<br>inwcl83aLtzJeKsznppqMyAIseaKIeAm6tT8uttNkr2zOymL/PbMpByTQeEFlyy1<br>poLBwrol0F4USc+owwIDAQAB<br>-----END PUBLIC KEY-----<br>*************************************************************<br>************************测试私钥*****************************<br>-----BEGIN PRIVATE KEY-----<br>MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKaQA2YLzj0g6e1h<br>BB1KAu8wwabxX+7zfwBMdqhnC/B6hjJ37/tbH5vHlt2S0lvjphupLW/PdVF1ezIk<br>haGk1ya0qFiKfByXzdou3Ml4qzOemmozIAix5ooh4Cbq1Py6202SvbM7KYv89syk<br>HJNB4QWXLLWmgsHCuiXQXhRJz6jDAgMBAAECgYAIF5cSriAm+CJlVgFNKvtZg5Tk<br>93UhttLEwPJC3D7IQCuk6A7Qt2yhtOCvgyKVNEotrdp3RCz++CY0GXIkmE2bj7i0<br>fv5vT3kWvO9nImGhTBH6QlFDxc9+p3ukwsonnCshkSV9gmH5NB/yFoH1m8tck2Gm<br>BXDj+bBGUoKGWtQ7gQJBANR/jd5ZKf6unLsgpFUS/kNBgUa+EhVg2tfr9OMioWDv<br>MSqzG/sARQ2AbO00ytpkbAKxxKkObPYsn47MWsf5970CQQDIqRiGmCY5QDAaejW4<br>HbOcsSovoxTqu1scGc3Qd6GYvLHujKDoubZdXCVOYQUMEnCD5j7kdNxPbVzdzXll<br>9+p/AkEAu/34iXwCbgEWQWp4V5dNAD0kXGxs3SLpmNpztLn/YR1bNvZry5wKew5h<br>z1zEFX+AGsYgQJu1g/goVJGvwnj/VQJAOe6f9xPsTTEb8jkAU2S323BG1rQFsPNg<br>jY9hnWM8k2U/FbkiJ66eWPvmhWd7Vo3oUBxkYf7fMEtJuXu+JdNarwJAAwJK0YmO<br>LxP4U+gTrj7y/j/feArDqBukSngcDFnAKu1hsc68FJ/vT5iOC6S7YpRJkp8egj5o<br>pCcWaTO3GgC5Kg==<br>-----END PRIVATE KEY-----</p>
<p><span style="font-size: 18px"> <strong>下面使用的相关函数功能介绍:</strong></span></p>
<p>openssl_pkey_get_public() 从证书中提取公钥<br>openssl_pkey_get_private() 从证书中提取私钥<br>openssl_public_encrypt() 公钥加密<br>openssl_private_decrypt() 私钥解密<br>openssl_private_encrypt() 私钥加密<br>openssl_public_decrypt() 公钥解密<br>base64_encode() 使用base64对数据重新编码<br>base64_decode() 将base64的数据解码</p>
<p>好了,准备工作到此结束。下面进行具体的codeing:</p>
<p><strong>第一步:将公私钥签名定义为常量</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">define</span>('RSA_PUBLIC', '<span style="color: rgba(0, 0, 0, 1)">-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmkANmC849IOntYQQdSgLvMMGm
8V/u838ATHaoZwvweoYyd+/7Wx+bx5bdktJb46YbqS1vz3VRdXsyJIWhpNcmtKhY
inwcl83aLtzJeKsznppqMyAIseaKIeAm6tT8uttNkr2zOymL/PbMpByTQeEFlyy1
poLBwrol0F4USc+owwIDAQAB
-----END PUBLIC KEY-----</span>'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">define</span>('RSA_PRIVATE','<span style="color: rgba(0, 0, 0, 1)">-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKaQA2YLzj0g6e1h
BB1KAu8wwabxX+7zfwBMdqhnC/B6hjJ37/tbH5vHlt2S0lvjphupLW/PdVF1ezIk
haGk1ya0qFiKfByXzdou3Ml4qzOemmozIAix5ooh4Cbq1Py6202SvbM7KYv89syk
HJNB4QWXLLWmgsHCuiXQXhRJz6jDAgMBAAECgYAIF5cSriAm+CJlVgFNKvtZg5Tk
93UhttLEwPJC3D7IQCuk6A7Qt2yhtOCvgyKVNEotrdp3RCz++CY0GXIkmE2bj7i0
fv5vT3kWvO9nImGhTBH6QlFDxc9+p3ukwsonnCshkSV9gmH5NB/yFoH1m8tck2Gm
BXDj+bBGUoKGWtQ7gQJBANR/jd5ZKf6unLsgpFUS/kNBgUa+EhVg2tfr9OMioWDv
MSqzG/sARQ2AbO00ytpkbAKxxKkObPYsn47MWsf5970CQQDIqRiGmCY5QDAaejW4
HbOcsSovoxTqu1scGc3Qd6GYvLHujKDoubZdXCVOYQUMEnCD5j7kdNxPbVzdzXll
9+p/AkEAu/34iXwCbgEWQWp4V5dNAD0kXGxs3SLpmNpztLn/YR1bNvZry5wKew5h
z1zEFX+AGsYgQJu1g/goVJGvwnj/VQJAOe6f9xPsTTEb8jkAU2S323BG1rQFsPNg
jY9hnWM8k2U/FbkiJ66eWPvmhWd7Vo3oUBxkYf7fMEtJuXu+JdNarwJAAwJK0YmO
LxP4U+gTrj7y/j/feArDqBukSngcDFnAKu1hsc68FJ/vT5iOC6S7YpRJkp8egj5o
pCcWaTO3GgC5Kg==
-----END PRIVATE KEY-----</span>');</pre>
</div>
<p><strong>第二步:进行公钥加密</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">公钥加密 </span>
<span style="color: rgba(128, 0, 128, 1)">$public_key</span> =<span style="color: rgba(0, 0, 0, 1)"> openssl_pkey_get_public(RSA_PUBLIC);
</span><span style="color: rgba(0, 0, 255, 1)">if</span>(!<span style="color: rgba(128, 0, 128, 1)">$public_key</span><span style="color: rgba(0, 0, 0, 1)">){
</span><span style="color: rgba(0, 0, 255, 1)">die</span>('公钥不可用'<span style="color: rgba(0, 0, 0, 1)">);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">第一个参数是待加密的数据只能是string,第二个参数是加密后的数据,第三个参数是openssl_pkey_get_public返回的资源类型,第四个参数是填充方式</span>
<span style="color: rgba(128, 0, 128, 1)">$return_en</span> = openssl_public_encrypt("hello world", <span style="color: rgba(128, 0, 128, 1)">$crypted</span>, <span style="color: rgba(128, 0, 128, 1)">$public_key</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">if</span>(!<span style="color: rgba(128, 0, 128, 1)">$return_en</span><span style="color: rgba(0, 0, 0, 1)">){
</span><span style="color: rgba(0, 0, 255, 1)">return</span>('加密失败,请检查RSA秘钥'<span style="color: rgba(0, 0, 0, 1)">);
}
</span><span style="color: rgba(128, 0, 128, 1)">$eb64_cry</span> = <span style="color: rgba(0, 128, 128, 1)">base64_encode</span>(<span style="color: rgba(128, 0, 128, 1)">$crypted</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "公钥加密数据:".<span style="color: rgba(128, 0, 128, 1)">$eb64_cry</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "<hr>";</pre>
</div>
<p><strong>第三步:测试使用私钥进行解密</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">私钥解密</span>
<span style="color: rgba(128, 0, 128, 1)">$private_key</span> =<span style="color: rgba(0, 0, 0, 1)"> openssl_pkey_get_private(RSA_PRIVATE);
</span><span style="color: rgba(0, 0, 255, 1)">if</span>(!<span style="color: rgba(128, 0, 128, 1)">$private_key</span><span style="color: rgba(0, 0, 0, 1)">){
</span><span style="color: rgba(0, 0, 255, 1)">die</span>('私钥不可用'<span style="color: rgba(0, 0, 0, 1)">);
}
</span><span style="color: rgba(128, 0, 128, 1)">$return_de</span> = openssl_private_decrypt(<span style="color: rgba(0, 128, 128, 1)">base64_decode</span>(<span style="color: rgba(128, 0, 128, 1)">$eb64_cry</span>), <span style="color: rgba(128, 0, 128, 1)">$decrypted</span>, <span style="color: rgba(128, 0, 128, 1)">$private_key</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">if</span>(!<span style="color: rgba(128, 0, 128, 1)">$return_de</span><span style="color: rgba(0, 0, 0, 1)">){
</span><span style="color: rgba(0, 0, 255, 1)">return</span>('解密失败,请检查RSA秘钥'<span style="color: rgba(0, 0, 0, 1)">);
}
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "私钥解密数据:".<span style="color: rgba(128, 0, 128, 1)">$decrypted</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "<hr>";</pre>
</div>
<p>跑一下可以看到结果:</p>
<p><img src="https://img2018.cnblogs.com/blog/1652001/201905/1652001-20190510171432423-1939569336.jpg" alt=""></p>
<p><strong>私钥加密,公钥解密的方式:</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">私钥加密</span>
<span style="color: rgba(128, 0, 128, 1)">$private_key</span> =<span style="color: rgba(0, 0, 0, 1)"> openssl_pkey_get_private(RSA_PRIVATE);
</span><span style="color: rgba(0, 0, 255, 1)">if</span>(!<span style="color: rgba(128, 0, 128, 1)">$private_key</span><span style="color: rgba(0, 0, 0, 1)">){
</span><span style="color: rgba(0, 0, 255, 1)">die</span>('私钥不可用'<span style="color: rgba(0, 0, 0, 1)">);
}
</span><span style="color: rgba(128, 0, 128, 1)">$return_en</span> = openssl_private_encrypt("hello world222222", <span style="color: rgba(128, 0, 128, 1)">$crypted</span>, <span style="color: rgba(128, 0, 128, 1)">$private_key</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">if</span>(!<span style="color: rgba(128, 0, 128, 1)">$return_en</span><span style="color: rgba(0, 0, 0, 1)">){
</span><span style="color: rgba(0, 0, 255, 1)">return</span>('加密失败,请检查RSA秘钥'<span style="color: rgba(0, 0, 0, 1)">);
}
</span><span style="color: rgba(128, 0, 128, 1)">$eb64_cry</span> = <span style="color: rgba(0, 128, 128, 1)">base64_encode</span>(<span style="color: rgba(128, 0, 128, 1)">$crypted</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "私钥加密数据".<span style="color: rgba(128, 0, 128, 1)">$eb64_cry</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "<hr>"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">公钥解密</span>
<span style="color: rgba(128, 0, 128, 1)">$public_key</span> =<span style="color: rgba(0, 0, 0, 1)"> openssl_pkey_get_public(RSA_PUBLIC);
</span><span style="color: rgba(0, 0, 255, 1)">if</span>(!<span style="color: rgba(128, 0, 128, 1)">$public_key</span><span style="color: rgba(0, 0, 0, 1)">){
</span><span style="color: rgba(0, 0, 255, 1)">die</span>('公钥不可用'<span style="color: rgba(0, 0, 0, 1)">);
}
</span><span style="color: rgba(128, 0, 128, 1)">$return_de</span> = openssl_public_decrypt(<span style="color: rgba(0, 128, 128, 1)">base64_decode</span>(<span style="color: rgba(128, 0, 128, 1)">$eb64_cry</span>), <span style="color: rgba(128, 0, 128, 1)">$decrypted</span>, <span style="color: rgba(128, 0, 128, 1)">$public_key</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">if</span>(!<span style="color: rgba(128, 0, 128, 1)">$return_de</span><span style="color: rgba(0, 0, 0, 1)">){
</span><span style="color: rgba(0, 0, 255, 1)">return</span>('解密失败,请检查RSA秘钥'<span style="color: rgba(0, 0, 0, 1)">);
}
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "公钥解密数据:".<span style="color: rgba(128, 0, 128, 1)">$decrypted</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "<hr>";</pre>
</div>
<p>跑一下可以看到结果:</p>
<p><img src="https://img2018.cnblogs.com/blog/1652001/201905/1652001-20190510172027663-1272222195.jpg" alt=""></p>
<p><span style="color: rgba(255, 0, 0, 1)">以上为使用php的默认填充方式加解密,请知悉</span></p><br><br>
来源:https://www.cnblogs.com/makalochen/p/10845033.html
頁:
[1]