[精选] php是如何使用 RSA私钥公钥 签名校验的呢?

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"
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
最美的不是下雨天,而是和你一起躲过的屋檐!
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 2

没理解错的话,前端a 可以用 后端b 的公钥加密作为签名,后端b 用自己对应的私钥解密来确认 前端a 的身份?

1年前 评论
tomcath (作者) 1年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!