【发布时间】:2021-11-08 04:34:24
【问题描述】:
我正在使用以下简单示例,使用 open ssl 加密和解密消息中的签名和数据。我正在尝试了解公钥和私钥以及签名如何与两个网站之间的数据通信一起使用。
我想做的是通过 curl 将数据发送到另一个网站上的 api,如果 openssl_verify 为真,则在 API 中能够验证签名并解压数据。
我在 API 部分的最后一个命令中收到错误,表明 $data 未定义。
我有三个问题:
- 如何解决此错误?
- 在 API 部分,我对确认签名和解压缩数据的最佳实践有点困惑。有没有比我想做的更好的方法来做到这一点?
- 使用 oauth2 是否可以更轻松地完成 API 验证过程(API 时没有用户输入)?
以下代码适用于网站 1,在用户提交 Web 表单后,它从表单中捕获名称并使用开放 ssl 加密名称并创建签名。
<?php
//Private key here for testing only, realize this has be be in highly secure location.
$private_key = <<<EOD
-----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBANDiE2+Xi/WnO+s120NiiJhNyIButVu6zxqlVzz0wy2j4kQVUC4Z
RZD80IY+4wIiX2YxKBZKGnd2TtPkcJ/ljkUCAwEAAQJAL151ZeMKHEU2c1qdRKS9
sTxCcc2pVwoAGVzRccNX16tfmCf8FjxuM3WmLdsPxYoHrwb1LFNxiNk1MXrxjH3R
6QIhAPB7edmcjH4bhMaJBztcbNE1VRCEi/bisAwiPPMq9/2nAiEA3lyc5+f6DEIJ
h1y6BWkdVULDSM+jpi1XiV/DevxuijMCIQCAEPGqHsF+4v7Jj+3HAgh9PU6otj2n
Y79nJtCYmvhoHwIgNDePaS4inApN7omp7WdXyhPZhBmulnGDYvEoGJN66d0CIHra
I2SvDkQ5CmrzkW5qPaE2oO7BSqAhRZxiYpZFb5CI
-----END RSA PRIVATE KEY-----
EOD;
$public_key = <<<EOD
-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANDiE2+Xi/WnO+s120NiiJhNyIButVu6
zxqlVzz0wy2j4kQVUC4ZRZD80IY+4wIiX2YxKBZKGnd2TtPkcJ/ljkUCAwEAAQ==
-----END PUBLIC KEY-----
EOD;
if (isset($_POST['name']) && $_POST['name']!="") {
$binary_signature = "";
$data = $_POST['name'];
echo $data;
openssl_public_encrypt($data, $encrypted, $public_key, OPENSSL_PKCS1_PADDING);
$data = base64_encode($encrypted);
openssl_sign($data, $binary_signature, $private_key, OPENSSL_ALGO_SHA256);
$binary_signature=base64_url_encode($binary_signature);
$url = "http://localhost/api/api.php?binary_signature=".$binary_signature;
$client = curl_init($url);
curl_setopt($client,CURLOPT_RETURNTRANSFER,true);
$response = curl_exec($client);
$result = json_decode($response);
echo "<table>";
echo "<tr><td>Name:</td><td>$result->data</td></tr>";
echo "<tr><td>Amount:</td><td>$result->amount</td></tr>";
echo "<tr><td>Response Code:</td><td>$result->response_code</td></tr>";
echo "<tr><td>Response Desc:</td><td>$result->response_desc</td></tr>";
echo "</table>";
}
function base64_url_encode($input) {
return strtr(base64_encode($input), '+/=', '-_,');
}
?>
这是 api 所在的网站 2。目标是验证签名并解包消息。我在 $ok = 处收到错误,因为它找不到 $data。
<?php
//Private key here for testing only, realize this has be be in highly secure location.
$private_key = <<<EOD
-----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBANDiE2+Xi/WnO+s120NiiJhNyIButVu6zxqlVzz0wy2j4kQVUC4Z
RZD80IY+4wIiX2YxKBZKGnd2TtPkcJ/ljkUCAwEAAQJAL151ZeMKHEU2c1qdRKS9
sTxCcc2pVwoAGVzRccNX16tfmCf8FjxuM3WmLdsPxYoHrwb1LFNxiNk1MXrxjH3R
6QIhAPB7edmcjH4bhMaJBztcbNE1VRCEi/bisAwiPPMq9/2nAiEA3lyc5+f6DEIJ
h1y6BWkdVULDSM+jpi1XiV/DevxuijMCIQCAEPGqHsF+4v7Jj+3HAgh9PU6otj2n
Y79nJtCYmvhoHwIgNDePaS4inApN7omp7WdXyhPZhBmulnGDYvEoGJN66d0CIHra
I2SvDkQ5CmrzkW5qPaE2oO7BSqAhRZxiYpZFb5CI
-----END RSA PRIVATE KEY-----
EOD;
$public_key = <<<EOD
-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANDiE2+Xi/WnO+s120NiiJhNyIButVu6
zxqlVzz0wy2j4kQVUC4ZRZD80IY+4wIiX2YxKBZKGnd2TtPkcJ/ljkUCAwEAAQ==
-----END PUBLIC KEY-----
EOD;
if (isset($_GET['binary_signature']) && $_GET['binary_signature']!="") {
$signature=$_GET['binary_signature'];
$signature=base64_decode($signature);
// Check signature
$ok = openssl_verify($data, $signature, $public_key, OPENSSL_ALGO_SHA256);
// more code would go here to test if verify is ok and then unpack the message.
?>
【问题讨论】:
-
第二个文件中的 $data 在哪里?它没有定义..为什么要知道它?你是不是漏掉了一行: $data = $_GET['encrypted_data'];或者类似的东西??? $data 来自哪里?你需要传递它并定义它。
-
@Shlomtzion 这对我来说对 API 中的变量 $data 很有意义。在第一个站点中,我认为
openssl_sign($data, $binary_signature, $private_key, OPENSSL_ALGO_SHA256);将数据打包在 $binary_signature 变量中。是这样吗?如果是这样,我如何在 API 中访问 $binary_signature 中的数据? -
$url = "localhost/api/api.php?binary_signature=".$binary_signature; 你在这里通过 ?binary_signature=".$binary_signature; 发送了 $_GET['binary_signature']所以在它后面加上: ."&data=".$data;所以你有: $url = "localhost/api/…; 现在你可以在 api 文件中使用 $_GET['data'] 了。