PHP RSA参数签名与验签

为了防止在支付通信过程中的参数数据被篡改或者伪造,采用RSA进行数据签名和验证签名。

RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。

生成公私钥

生成 RSA 私钥 PEM 文件:

1
# openssl genrsa -out rsa_private_key.pem 2048

根据已经生成的私钥再生成公钥:

1
# openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

注意:生成后的rsa_private_key.pem私钥不能直接用于Java进行加密,原因是Java使用的PKCS#8格式的私钥,但PHP不会有问题。Java的keytool生成的RSA公钥密私钥是16进制字符串,PHP用openssl生成的公钥私钥是基于base64格式的字符串或者二进制格式,这两种不同的公约密钥并不能直接转化。

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
82
83
84
85
86
87
88
89
90
<?php

$data = "name=Joe Ye&blog=www.appblog.cn&city=杭州";

$sign = RSA::sign($data);
echo $sign;
echo '<br>';
echo 'result: ' . RSA::verify($data, $sign);

class RSA
{

public static function sign($data)
{
$priKey = file_get_contents('D:/rsa_private_key.pem');
/*
$priKey = '-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA8Yf/PlCkJlG72pKWkx+ZKbTiS/hPmT1YtRz6d6bow0nROY5X
e+mGcLhrqNBfUGGsdLYVN6Xa+/YQYyvp9pXGMxmv5a22oFQXQhNX7+Gl0gE/kXKq
guIY0ztE+thmzabFl0+ZNR420la7cl13bJAdXybl8GBjFkXeUuZAkCWHN672JEuc
rMPi6IUTNB+/ksa0jsjge/ixrawm9Hz+XuF8xIYPILSaWixgFibpHR6lEVrSLCnE
aTbSSO7ZQW5areMe37qoUl4osep/eXXJCeCXgaBqExNa7n+LR5JFoMNCAtDsHSzP
Z2moARBLVh0AcyyYq7Xwx9dW5uQ8UlQlfYADXwIDAQABAoIBAH+6re7kcoqZOsDy
OJMBaNw3fl0yqdWeLaVJ9+MC76EnDnBjqDwtWR2PSc/yshUuMidei4XsPgx1KmFn
vcjbl/86HF1YKnZLQil9VUnUiP6wDk/61dV1gC9k7qvBeUxUX7YPMDR5EADYQTTP
3PIanI3PYlZmgsAqntI0Vfxk/EcjRpbGStGQ7yfXVwsNED6PaH63MTYXjP68V++2
wKhH4aNJW6a1qNtKVCnmEyNewFhEQT4EG/mUDphBWCA1AgK5XEH2gNBs+5UixN8h
uNNAznKxADDoolipf6laObcxSZPyU2SwyFYIsFfkuLH8tXsDtbdywc/kcbOLkSM5
wtXQZhECgYEA/YXc3YqXrTSFgSl8RwabfFDJQqjCq7P3963oQZkySvEB5NrYmqIy
c0ZrzuSkTPK0cUv9LXjiv5JB502IdlDEEzhyEvnJNqkaSAXmw5UakPsI9hCVu8vg
/hZOrlEDQXfnERzbfveYWOX9BG2S+d4X1qmd9HxFVb+keeEnYoU5VeUCgYEA8+Qj
t8raDV4H8LBUtPTw424OoFd7buuOZ8RWe0a1BAlMEL6ppCYopBy5wBwhJbyNoyyw
HO53f06Zy+43gsaaxrpdUZ69bFatx+bbYgQeMUhEyslbk1Y8sXu0o+6Q+WXwBUni
r90k+uVS02TE4o2gcfmFmyiOfdY9YEUo4Dkt3/MCgYBgXJccpecM8J+l/my8WmiT
EenNqnOD6/3eaH2VIXOaRIzhvcUC0Y+3fRbRJtrEXKP1RFrRA9e71Q2zqyapQf2l
CJljWQn/+rqAka2qvWvBm4lGbftbzBySt0vkueow4jAzsvJDCj0f3RsUqclpq98H
uqTNHscD1rnfkZL0wYqPeQKBgQCJmJaGJI2sqPY11mWTyfT1eqwJzhE3XPH0nRJl
bljFtDET6V1v3I9lN0ecmMIitiP6gUXCrM8CJegi43yx7TZ5E79+Qt5/ds+ITjhL
LiOSjkExXzSpBSgswawCKJ/l9JrbgPnBWjR40FRQKzPg1SJF6w5zoQfy+qGZ5KrR
BbFZ/QKBgQC40Fe4hDlouBtkX9aQO2gj0m4cAcuJkZ5bkoiWUjOCMK5opTC01/5q
VjQyWn7tjESggCXKrY7a+HTGMJJH/QM9yopVCI4kYXBoPO6s0R8jcGiTSnYRA/K7
uxjloGvgwqUxZhlwUXi6tct6gXEolNkPGDL5uUiQCV6gpBpih6l5pA==
-----END RSA PRIVATE KEY-----';*/

//转换为openssl密钥,必须是没有经过pkcs8转换的私钥
$res = openssl_get_privatekey($priKey);

//调用openssl内置签名方法,生成签名$sign
//openssl_sign($data, $sign, $res, OPENSSL_ALGO_MD5);
//openssl_sign($data, $sign, $res, OPENSSL_ALGO_SHA1);
openssl_sign($data, $sign, $res);

openssl_free_key($res);

$sign = base64_encode($sign);
return $sign;
}

/**
* RSA验证签名
* $data 为要验证的数据字符串
* $sign 是需要验证的签名数据,是直接从URL中取到的$_POST["sign"]型参数,函数里面会进行base64_decode的
* return 验签是否通过,为BOOL值
*/
public static function verify($data, $sign)
{
//读取公钥文件,也就是签名方公开的公钥,用来验证这个data是否真的是签名方发出的
$pubKey = file_get_contents('D:/rsa_public_key.pem');
/*
$pubKey = '-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8Yf/PlCkJlG72pKWkx+Z
KbTiS/hPmT1YtRz6d6bow0nROY5Xe+mGcLhrqNBfUGGsdLYVN6Xa+/YQYyvp9pXG
Mxmv5a22oFQXQhNX7+Gl0gE/kXKqguIY0ztE+thmzabFl0+ZNR420la7cl13bJAd
Xybl8GBjFkXeUuZAkCWHN672JEucrMPi6IUTNB+/ksa0jsjge/ixrawm9Hz+XuF8
xIYPILSaWixgFibpHR6lEVrSLCnEaTbSSO7ZQW5areMe37qoUl4osep/eXXJCeCX
gaBqExNa7n+LR5JFoMNCAtDsHSzPZ2moARBLVh0AcyyYq7Xwx9dW5uQ8UlQlfYAD
XwIDAQAB
-----END PUBLIC KEY-----';*/

$res = openssl_get_publickey($pubKey);

//调用openssl内置方法验签,返回bool值
$result = (bool) openssl_verify($data, base64_decode($sign), $res);

openssl_free_key($res);
return $result;
}
}

?>

Powered by AppBlog.CN     浙ICP备14037229号

Copyright © 2012 - 2020 APP开发技术博客 All Rights Reserved.

访客数 : | 访问量 :