RSA算法是种能同时用于加密和数字签名的算法,也是被研究得最广泛的公钥算法。而公钥私钥的加密解密也会使一些小伙伴疑惑,这里稍微简单说一下,再简单地实现一下。
首先,公钥加密私钥可以解密。其次,私钥加密公钥可以解密。再深一步来说,公钥负责加密,私钥负责解密。私钥负责签名,公钥负责验证。公钥就是给大家用的,私钥就是给自己用的,必须小心保存。
举个栗子,A想向B发送一条加密的信息,使用B的公钥加密,这样只有拥有对应私钥的B才能解密,确保了信息没有被别人看到,其次A可以用自己的私钥加密一条信息发送给B,B用A的公钥验证,因为只有A拥有私钥所以能证明此信息是A所发的。(如果A是在借钱B经过公钥验证后就知道是本人而不是骗子了)
网上看了很多文章都没有php相关的例子,这里给大家简单的写了一个。
生成 RSA 私钥
$ openssl genrsa -out rsa_private_key.pem 1024
生成 RSA 公钥(php和java都用私钥生成公钥)
$ openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
PHP 版本加密,认证:
<?php
$privateKeyString=
<<<EOF
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDRHaNFj+BW4g6A+0NOrPq1XOACEsCZUuJNJsq6JbcvN9JgpPKG
C6zlvEwiibsAk5NqLvYmdbqiIC41VJ/T4aq7RFc/k5eo2FJlfzoRKMIG9yVsp6mr
NLOkrDrbbN+GS02463L3oDhlZVncXfXWZNbeC0vrBzjM3QsZIqHYVQQc6QIDAQAB
AoGAO6fA1C9fSGnkyVbktKUUQHjmTrEa0KKcfHX8j24C/C1ojrl/lk3uXPuCnLe9
6UQwYbJT9lTPkUCs7fnePou6MH4acPsOHnwJ3PpQrO5H01Z8sZQkD/KIyk1LPaGl
8zvKlTOgrSg4h8JLk7i9PI8q2Yp75rquVZglQ7m6H1GXNiECQQDszsnMjAptFvnb
bs29wiuRSV7iqkigZTokLtJjJ1qw5fpNipJbAN/jhwAFEe1aMAno/rpru0l3EuGG
Z85M+pfzAkEA4hBODEnRU5D1fwUcp4LY5spOm2dk5h/LZJbI/5et0y2Qah+YFe0k
hgzV70dNUmjteYg3axzksUuipZE4bSoqswJBALlFSCjaX8XdtfnyBNGzunZe2ven
lk63I/fvEfc1cQT5yQ0lnz/HvWK72k4dKn/nGbnKoXtr+hxJD10ilgsv+/UCQGnt
g/TkHg8PTMmxJoUjnek/AOh24WOnoFHJCfQiKdRbdGEV3tjfXw7lMtXFTmkAO86H
0pgBWPPu4g685njYmlsCQGHxbxNr2ybRqgIuqmiNO7jldtcXMqzaF4w1BHS5C0mk
A6+i/KEJ5yLVv6lmDPO1WDbbt81cYO8RGEQ7DblIRoc=
-----END RSA PRIVATE KEY-----
EOF;
// 私钥加密
$privateKey = openssl_pkey_get_private($privateKeyString);
// 签名字符串
$message = '12345678';
$signature = null;
if (openssl_sign($message, $signature, $privateKey, OPENSSL_ALGO_SHA256)) {
$signature = base64_encode($signature);
echo 'signature:', $signature,PHP_EOL;
} else {
echo openssl_error_string();
}
// 公钥验证签名
$publicKeyString =
<<<EOF
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRHaNFj+BW4g6A+0NOrPq1XOAC
EsCZUuJNJsq6JbcvN9JgpPKGC6zlvEwiibsAk5NqLvYmdbqiIC41VJ/T4aq7RFc/
k5eo2FJlfzoRKMIG9yVsp6mrNLOkrDrbbN+GS02463L3oDhlZVncXfXWZNbeC0vr
BzjM3QsZIqHYVQQc6QIDAQAB
-----END PUBLIC KEY-----
EOF;
// 公钥的第二种格式,也是可以的
$publicKeyString = "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRHaNFj+BW4g6A+0NOrPq1XOAC\nEsCZUuJNJsq6JbcvN9JgpPKGC6zlvEwiibsAk5NqLvYmdbqiIC41VJ/T4aq7RFc/\nk5eo2FJlfzoRKMIG9yVsp6mrNLOkrDrbbN+GS02463L3oDhlZVncXfXWZNbeC0vr\nBzjM3QsZIqHYVQQc6QIDAQAB\n-----END PUBLIC KEY-----";
$publicKey = openssl_pkey_get_public($publicKeyString);
$return = [
'code' => 0,
'message' => 'error'
];
// 执行验证
$success = openssl_verify($message, base64_decode($signature), $publicKey, OPENSSL_ALGO_SHA256);
if ($success === -1) {
$return['message'] = ''.openssl_error_string();
} elseif ($success === 1) {
$return['code'] = 1;
$return['message'] = 'success';
} else {
$return['message'] = openssl_error_string();
}
echo 'openssl_verify result:';
var_dump($return);
这里都写在一个文件里了,为了方便测试,其实大家看相关的注释就能看的出来的
执行脚本,结果如下:
>php -f depakin.php
signature:q6nCWEEXHRubgZEFT3wkjVd5gmmDucBCAiX20HBrpSBxPevlxCTwkMZ+35nVpVoj+Rmz3m+5qWBZ2m0q8POoDFr5YPsANSos0cM1Nr1zC9ju6SRCBpRmiGKLxzniuehkrRyxbWf+rLthmiSDnQa/peWw5Y7hsVT68yR8AoCovRY=
openssl_verify result:
array(2) {
'code' =>
int(1)
'message' =>
string(7) "success"
}