什么是RSA加密?
RSA (详见维基百科)算法是现今使用最广泛的公钥密码算法,也是号称地球上最安全的加密算法,与 md5 和 sha1 不同,到目前为止,也只有极短的RSA加密被破解。
使用场景
- 为移动端(IOS,安卓)编写 API 接口
- 进行支付、真实信息验证等安全性需求较高的通信
- 与其他第三方或合作伙伴进行重要的数据传输,用于外部商户系统和本系统之间报文的安全性验证。
生成私钥、公钥
1、生成原始 RSA 私钥文件
代码语言:javascript复制1openssl genrsa -out private_key.pem 1024
说明:生成RSA私钥,private_key.pem
为存放私钥的文件名,长度1204
2、将原始 RSA 私钥转换为 pkcs8 格式
代码语言:javascript复制1openssl pkcs8 -topk8 -inform PEM -in private_key.pem -outform PEM -nocrypt -out rsa_private_key.pem
说明:把RSA私钥转换成PKCS8格式,转化后的私钥 rsa_private_key.pem
3、生成 RSA 公钥
代码语言:javascript复制1openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
说明:生成RSA公钥文件rsa_public_key.pem
4、最后会有三个文件
代码语言:javascript复制1λ ls
2private_key.pem rsa_private_key.pem rsa_public_key.pem
文本打开rsa_private_key.pem
、rsa_public_key.pem
,里面存放的是私钥、公钥。商户需要把公钥字符串发给易付宝的业务人员,私钥商户自行保存。
php-rsa 加密解密
Rsa 服务器类库
代码语言:javascript复制 1<?php
2/**.-------------------------------------------------------------------------------------------------------------------
3 * | Github: https://github.com/Tinywan
4 * | Blog: http://www.cnblogs.com/Tinywan
5 * |--------------------------------------------------------------------------------------------------------------------
6 * | Author: Tinywan(ShaoBo Wan)
7 * | DateTime: 2018/8/30 22:48
8 * | Mail: 756684177@qq.com
9 * | Desc: php-rsa 加密解密 https://segmentfault.com/a/1190000012083428
10 * '------------------------------------------------------------------------------------------------------------------*/
11
12namespace appcommonlibrary;
13
14
15class Rsa
16{
17 /**
18 * @var array 默认配置
19 */
20 private $_config = [
21 'public_key' => '-----BEGIN PUBLIC KEY-----
22MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCbtLA7lMfUvpBgfgzouiPgcnbL
23DnEcuCK0gMub/EAEqmr82sl 9tH1iQb1w/hgQLptVRxAuUOa03XqlnG3wkAegtQt
244Q5ZtHSSomE8/5FXJvQfGTCz5RARyM0MiLTMZJGhLdVT6O8uCYIrPRQq7u6NVLs9
256YDmtzX2do/sTsWCAwIDAQAB
26-----END PUBLIC KEY-----',
27 'private_key' => '-----BEGIN RSA PRIVATE KEY-----
28MIICWwIBAAKBgQCbtLA7lMfUvpBgfgzouiPgcnbLDnEcuCK0gMub/EAEqmr82sl
299tH1iQb1w/hgQLptVRxAuUOa03XqlnG3wkAegtQt4Q5ZtHSSomE8/5FXJvQfGTCz
305RARyM0MiLTMZJGhLdVT6O8uCYIrPRQq7u6NVLs96YDmtzX2do/sTsWCAwIDAQAB
31AoGAfnO3zCuAPp6k0jiMc1T4XgeXwkDwS8qfJMiUkxHBTAi66q8khSAeU7H9HQsS
32Y9ktji1YzJeo98xULzgPEpWHS/uhA8VZa16TLy9Yfadn2t wpWpEJ9ZA4jjEqfQj
33DDxcUc/pEv5siaE/bU8uls4o2nAiuWnI2n5FGrQa2OziGUECQQDPOh3KD2AOZtEF
34p7i0yxYXe4dCKwenfw5q7l933RgqMXsVR1EAGzAUdIs71hTye6ibhva eJRfndoV
35Jq2IHjOdAkEAwFpOZR8j3Cl4zEk/9D9WEnSa8VWLe76vb7DfgfwkSAhs/f2MNF1I
36zy9W5tPHRiMzaHNgPBFX9tw2u5QzsgOqHwJAPl3zUTjHZA41okoUIPVuNKsMzjE9
37IH/wyuXq/ZwhBbHWpVTNYAbOtZlNvjh0HXZyDDzWTgTkQtKzK J0H59XUQJARukD
38vYOdVKx1O9pFGWW/9U3HUPCYWyYQxrwNqX2qYmO4ymmOJj 9d6OcBbxM2i5f5UGj
39WIGMTBUimEQqSpXPQQJAIkHC2GknUv8HaBRLXxYTIAjj78a0pQT2bYlI6R04AwUZ
40ljBaUGvvdYJ3CGZ32Xk12Te2fMJj5h/yLyEr8uzpzw==
41-----END RSA PRIVATE KEY-----',
42 ];
43
44 /**
45 * 构造函数
46 * Rsa constructor.
47 * @param $private_key_filepath
48 * @param $public_key_filepath
49 */
50 public function __construct($private_key_filepath = null, $public_key_filepath = null)
51 {
52 if(!empty($private_key_filepath) && !empty($public_key_filepath)){
53 $this->_config['private_key'] = $this->_getContents($private_key_filepath);
54 $this->_config['public_key'] = $this->_getContents($public_key_filepath);
55 }
56 }
57
58 /**
59 * @uses 获取文件内容
60 * @param $file_path string
61 * @return bool|string
62 */
63 private function _getContents($file_path)
64 {
65 file_exists($file_path) or die ('密钥或公钥的文件路径错误');
66 return file_get_contents($file_path);
67 }
68
69 /**
70 * @uses 获取私钥
71 * @return bool|resource
72 */
73 private function _getPrivateKey()
74 {
75 $private_key = $this->_config['private_key'];
76 return openssl_pkey_get_private($private_key);
77 }
78
79 /**
80 * @uses 获取公钥
81 * @return bool|resource
82 */
83 private function _getPublicKey()
84 {
85 $public_key = $this->_config['public_key'];
86 return openssl_pkey_get_public($public_key);
87 }
88
89 /**
90 * 私钥加密 (使用公钥解密)
91 * @param string $data
92 * @return null|string
93 */
94 public function privateEncrypt($data = '', $padding = OPENSSL_PKCS1_PADDING)
95 {
96 if (!is_string($data)) return null;
97 $encrypted = '';
98 $chunks = str_split($data, 117);
99 foreach ($chunks as $chunk) {
100 $partialEncrypted = '';
101 $encryptionOk = openssl_private_encrypt($chunk, $partialEncrypted, $this->_getPrivateKey(), $padding);
102 if ($encryptionOk === false) {
103 return null;
104 }
105 $encrypted .= $partialEncrypted;
106 }
107 $encrypted = base64_encode($encrypted);
108 return $encrypted;
109 }
110
111 /**
112 * 公钥加密(使用私钥解密)
113 * @param string $data 加密字符串
114 * @param int $padding
115 * @return null|string
116 */
117 public function publicEncrypt($data = '', $padding = OPENSSL_PKCS1_PADDING)
118 {
119 if (!is_string($data)) return null;
120 $encrypted = '';
121 $chunks = str_split($data, 117);
122 foreach ($chunks as $chunk) {
123 $partialEncrypted = '';
124 $encryptionOk = openssl_public_encrypt($chunk, $partialEncrypted, $this->_getPublicKey(), $padding);
125 if ($encryptionOk === false) {
126 return null;
127 }
128 $encrypted .= $partialEncrypted;
129 }
130 $encrypted = base64_encode($encrypted);
131 return $encrypted;
132 }
133
134 /**
135 * @uses 私钥解密 (使用公钥加密)
136 * @param string $encrypted
137 * @return null
138 */
139 public function privateDecrypt($encrypted = '')
140 {
141 if (!is_string($encrypted)) return null;
142 $decrypted = '';
143 $chunks = str_split(base64_decode($encrypted), 128);
144 foreach ($chunks as $chunk) {
145 $partial = '';
146 $decryptIsTrue = openssl_private_decrypt($chunk, $partial, $this->_getPrivateKey());
147 if ($decryptIsTrue === false) {
148 return null;
149 }
150 $decrypted .= $partial;
151 }
152 return $decrypted;
153 }
154
155 /**
156 * 公钥解密 (使用私钥解密)
157 * @param string $encrypted 被解密字符串
158 * @return null
159 */
160 public function publicDecrypt($encrypted = '')
161 {
162 if (!is_string($encrypted)) return null;
163 $decrypted = '';
164 $chunks = str_split(base64_decode($encrypted), 128);
165 foreach ($chunks as $chunk) {
166 $partial = '';
167 $decryptIsTrue = openssl_public_decrypt($chunk, $partial, $this->_getPublicKey());
168 if ($decryptIsTrue === false) {
169 return null;
170 }
171 $decrypted .= $partial;
172 }
173 return $decrypted;
174 }
175
176 /**
177 * 私钥验签
178 * @param $data string 验签内容
179 * @param $signature string 签名字符串
180 * @param int $signature_alg
181 * @return bool
182 */
183 public function privateSign($data, $signature, $signature_alg = OPENSSL_ALGO_SHA1)
184 {
185 $result = openssl_sign($data, base64_decode($signature), $this->_getPrivateKey(), $signature_alg);
186 openssl_free_key($this->_getPrivateKey());
187 return $result === 1 ? true : false;
188 }
189
190 /**
191 * 公钥验签
192 * @param $data string 验签内容
193 * @param $signature string 签名字符串
194 * @param int $signature_alg
195 * @return bool
196 */
197 public function publicSign($data, $signature, $signature_alg = OPENSSL_ALGO_SHA1)
198 {
199 $result = openssl_verify($data, base64_decode($signature), $this->_getPublicKey(), $signature_alg);
200 openssl_free_key($this->_getPublicKey());
201 return $result === 1 ? true : false;
202 }
203}
204
使用案例
- 公钥加密、私钥解密
1$rsa = new Rsa();
2// 加密明文
3$crypt_text = '公钥加密、私钥解密';
4echo '加密明文:' . $crypt_text.PHP_EOL;
5
6$public_encrypt_data = $rsa->publicEncrypt($crypt_text);
7echo '公钥加密后数据:' . $public_encrypt_data.PHP_EOL; // 一直在变化
8
9$private_decrypt_data = $rsa->privateDecrypt($public_encrypt_data);
10echo '私钥解密数据: ' . $private_decrypt_data.PHP_EOL;
加密明文:公钥加密、私钥解密 公钥加密后数据:QHdj15P6l1gJbjNlD7spKT7KjCJJ0Qg5c8JjLBAS9hvhkq8eRuaNY/dDrboD3t40NvyPI8SBFBkDTjJ5IDyqTTSfthUROvasMD7wCPRYGaOt5to ygfvV5t4CyYQEvSSflqimWvffRs0L8fs3pqE2kLD/AHOC94 ZBNFfzTTtVA= 私钥解密数据: 公钥加密、私钥解密
- 私钥加密、公钥解密
1$rsa = new Rsa();
2// 加密明文
3$crypt_text = '私钥加密、公钥解密';
4echo '加密明文:' . $crypt_text.PHP_EOL;
5
6$private_encrypt_data = $rsa->privateEncrypt($crypt_text);
7echo '私钥加密后数据:' . $private_encrypt_data..PHP_EOL; // 不变
8
9$public_decrypt_data = $rsa->publicDecrypt($private_encrypt_data);
10echo '公钥解密数据: ' . $public_decrypt_data..PHP_EOL;
加密明文:私钥加密、公钥解密 私钥加密后数据:dDzAs7kj9z7kS7Zbcz6sNLP sIOnXp2qFGr4RepZcZp9XzCt8Tt Kd/NIo4S20hjAvBiurvSHaR6LLL5ur5dc4vkFGkV bGaT2SlhC4JkvYt4N2T9EiQupwcCtlk dcENLexWiCvZtuzk3peK H7AUWqFeOlmGRZb3De7bP heY= 公钥解密数据: 私钥加密、公钥解密
- 测试结果:
私钥加密
是不变的,公钥加密
后的字符串一直是变化的