PHP 使用非对称加密算法(RSA)

释放双眼,带上耳机,听听看~!

转自:https://www.cnblogs.com/xuweiqiang/p/9784584.html

常用的rsa密钥有两种格式,一种为pkcs1,首尾分别为:


1
2
3
4
5
6
7
1# 公钥
2-----BEGIN RSA PUBLIC KEY-----
3-----END RSA PUBLIC KEY-----
4# 私钥
5-----BEGIN RSA PRIVATE KEY-----
6-----END RSA PRIVATE KEY-----
7

另一种为pkcs8,首尾分别为:


1
2
3
4
5
6
7
1# 公钥
2-----BEGIN PUBLIC KEY-----
3-----END PUBLIC KEY-----
4# 私钥
5-----BEGIN PRIVATE KEY-----
6-----END PRIVATE KEY-----
7

这里加解密: 公钥是私钥转换pkcs8格式后生成(其实用pkcs1生产的公钥也是一样的),私钥还是用的pkcs1格式

具体实现:

1、加密解密的第一步是生成公钥、私钥对,私钥加密的内容能通过公钥解密(反过来亦可以)


1
2
1下载开源RSA密钥生成工具openssl(通常Linux系统都自带该程序),解压缩至独立的文件夹,进入其中的bin目录,执行以下命令:
2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1openssl genrsa -out rsa_private_key.pem 1024
2openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out private_key.pem
3openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
4
5第一条命令生成原始 RSA私钥文件 rsa_private_key.pem
6第二条命令将原始 RSA私钥转换为 pkcs8格式
7第三条生成RSA公钥 rsa_public_key.pem
8
9
10#############常用命令集合
11
12##openssl 生成pkcs1格式的私钥,密钥长度1024位, (PKCS1)
13openssl genrsa -out private_pkcs1.pem 1024
14
15##PKCS1私钥转换为PKCS8
16openssl pkcs8 -topk8 -inform PEM -in private_pkcs1.pem -outform pem -nocrypt -out private_pkcs8.pem
17
18##pkcs8格式私钥转为pkcs1格式私钥:
19openssl rsa -in private_pkcs8.pem -out private_pkcs1_from_pkcs8.pem
20
21##从pkcs1私钥中生成pkcs8公钥
22openssl rsa -in private_pkcs1.pem -pubout -out public_pkcs8.pem
23
24##从pkcs8私钥中生成pkcs8公钥
25openssl rsa -in private_pkcs8.pem -pubout -out public_pkcs8.pem
26
27##pkcs8公钥转pkcs1公钥,这个是打印出来的,需要复制一下放到文件里面(p_pkcs1.pem),空了再找命令
28openssl rsa -pubin -in public_pkcs8.pem -RSAPublicKey_out
29
30##pkcs1公钥转换为pkcs8公钥,这个是打印出来的,需要复制一下放到文件里面,空了再找命令
31openssl rsa -RSAPublicKey_in -in p_pkcs1.pem -pubout
32
33

1
2
3
4
1上面几个就可以看出:通过私钥能生成对应的公钥
2
3也有一些网站提供生成rsa公钥私钥的服务(本人未尝试):http://www.bm8.com.cn/webtool/rsa/
4

2、PHP的加密解密类库:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
1<?php
2
3
4class Rsa {
5
6    /**    
7     * 获取私钥    
8     * @return bool|resource    
9     */    
10    private static function getPrivateKey()
11    {        
12        $abs_path = dirname(__FILE__) . '/rsa_private_key.pem';
13        $content = file_get_contents($abs_path);    
14        return openssl_pkey_get_private($content);    
15    }    
16
17    /**    
18     * 获取公钥    
19     * @return bool|resource    
20     */    
21    private static function getPublicKey()
22    {  
23        $abs_path = dirname(__FILE__) . '/rsa_public_key.pem';
24        $content = file_get_contents($abs_path);    
25        return openssl_pkey_get_public($content);    
26    }
27
28    /**    
29     * 私钥加密    
30     * @param string $data    
31     * @return null|string    
32     */    
33    public static function privEncrypt($data = '')    
34    {        
35        if (!is_string($data)) {            
36            return null;      
37        }        
38        return openssl_private_encrypt($data,$encrypted,self::getPrivateKey()) ? base64_encode($encrypted) : null;    
39    }    
40
41    /**    
42     * 公钥加密    
43     * @param string $data    
44     * @return null|string    
45     */    
46    public static function publicEncrypt($data = '')  
47    {        
48        if (!is_string($data)) {            
49            return null;        
50        }        
51        return openssl_public_encrypt($data,$encrypted,self::getPublicKey()) ? base64_encode($encrypted) : null;    
52    }    
53
54    /**    
55     * 私钥解密    
56     * @param string $encrypted    
57     * @return null    
58     */    
59    public static function privDecrypt($encrypted = '')    
60    {        
61        if (!is_string($encrypted)) {            
62            return null;        
63        }        
64        return (openssl_private_decrypt(base64_decode($encrypted), $decrypted, self::getPrivateKey())) ? $decrypted : null;    
65    }    
66
67    /**    
68     * 公钥解密    
69     * @param string $encrypted    
70     * @return null    
71     */    
72    public static function publicDecrypt($encrypted = '')    
73    {        
74        if (!is_string($encrypted)) {            
75            return null;        
76        }        
77    return (openssl_public_decrypt(base64_decode($encrypted), $decrypted, self::getPublicKey())) ? $decrypted : null;    
78    }
79
80}
81

 

调用demo:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1<?php
2
3require_once "Rsa.php";
4$rsa = new Rsa();
5$data['name'] = 'Tom';
6$data['age']  = '20';
7$privEncrypt = $rsa->privEncrypt(json_encode($data));
8echo '私钥加密后:'.$privEncrypt.'<br>';
9
10$publicDecrypt = $rsa->publicDecrypt($privEncrypt);
11echo '公钥解密后:'.$publicDecrypt.'<br>';
12
13$publicEncrypt = $rsa->publicEncrypt(json_encode($data));
14echo '公钥加密后:'.$publicEncrypt.'<br>';
15
16$privDecrypt = $rsa->privDecrypt($publicEncrypt);
17echo '私钥解密后:'.$privDecrypt.'<br>';
18

代码截图实例:

附,私钥转码为pkcs8 可能会报错:


1
2
3
1unable to load Private Key
2139656125785928:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:703:Expecting: ANY PRIVATE KEY
3

是由于私钥没有换行导致,可以强行进行换行 


1
2
3
4
5
6
7
8
9
10
11
1<?php
2$str = "错误私钥";
3$dataArr = str_split($str, 64);
4echo "-----BEGIN RSA PRIVATE KEY-----".PHP_EOL;
5foreach ($dataArr as $trunk) {
6    echo $trunk.PHP_EOL;
7}
8echo "-----END RSA PRIVATE KEY-----".PHP_EOL;
9//执行下命令
10/usr/local/bin/php  ./trans.php > test.pem
11

处理完毕之后在执行命令转换格式:


1
2
1openssl pkcs8 -topk8 -inform PEM -in test.pem -outform PEM -nocrypt -out rsa_private_key.pem
2

 

 

 

给TA打赏
共{{data.count}}人
人已打赏
安全技术

C++中引用和指针的区别

2022-1-11 12:36:11

安全网络

ASP.NET Core微服务之基于App.Metrics+InfluxDB+Grafana实现统一性能监控

2021-8-18 16:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索