PHP Conference Japan 2024

openssl_sign

(PHP 4 >= 4.0.4, PHP 5, PHP 7, PHP 8)

openssl_sign生成签名

描述

openssl_sign(
    字符串 $data,
    字符串 &$signature,
    #[\SensitiveParameter] OpenSSLAsymmetricKey|OpenSSLCertificate|数组|字符串 $private_key,
    字符串|整数 $algorithm = OPENSSL_ALGO_SHA1
): 布尔值

openssl_sign() 使用与 private_key 关联的私钥生成密码数字签名,从而计算指定 data 的签名。请注意,数据本身不会被加密。

参数

data

要签名的字符串数据

signature

如果调用成功,则签名将返回到 signature

private_key

OpenSSLAsymmetricKey - 由 openssl_get_privatekey() 返回的密钥

字符串 - PEM 格式的密钥

algorithm

整数 - 这些 签名算法 之一。

字符串 - openssl_get_md_methods() 返回的有效字符串,例如,“sha256WithRSAEncryption” 或 “sha384”。

返回值

成功时返回 true,失败时返回 false

变更日志

版本 描述
8.0.0 private_key 现在接受 OpenSSLAsymmetricKeyOpenSSLCertificate 实例;以前,它接受类型为 OpenSSL keyOpenSSL X.509资源

示例

示例 #1 openssl_sign() 示例

<?php
// 假设 $data 包含要签名的资料

// 从文件中获取私钥并准备好
$pkeyid = openssl_pkey_get_private("file://src/openssl-0.9.6/demos/sign/key.pem");

// 计算签名
openssl_sign($data, $signature, $pkeyid);

// 释放内存中的密钥
openssl_free_key($pkeyid);
?>

示例 #2 openssl_sign() 示例

<?php
// 要签名的资料
$data = 'my data';

// 创建新的私钥和公钥
$new_key_pair = openssl_pkey_new(array(
"private_key_bits" => 2048,
"private_key_type" => OPENSSL_KEYTYPE_RSA,
));
openssl_pkey_export($new_key_pair, $private_key_pem);

$details = openssl_pkey_get_details($new_key_pair);
$public_key_pem = $details['key'];

// 创建签名
openssl_sign($data, $signature, $private_key_pem, OPENSSL_ALGO_SHA256);

// 保存以备后用
file_put_contents('private_key.pem', $private_key_pem);
file_put_contents('public_key.pem', $public_key_pem);
file_put_contents('signature.dat', $signature);

// 验证签名
$r = openssl_verify($data, $signature, $public_key_pem, "sha256WithRSAEncryption");
var_dump($r);
?>

参见

添加备注

用户贡献的备注 2 条备注

edmarw at yahoo dot com
17 年前
如果您只需要一个简单的私钥/公钥对,这可能会有所帮助

<?php

$data
= "啤酒真不错.. 嗝...";

// 你可以使用以下命令生成简单的私钥/公钥对:
// openssl genrsa 512 > private_key.txt
// openssl rsa -pubout < private_key.txt > public_key.txt

// 重要提示:以下密钥对仅供测试使用。
// 出于安全考虑,您必须为生产环境生成新的密钥对。

$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;

$binary_signature = "";

// 至少在 PHP 5.2.2 / OpenSSL 0.9.8b (Fedora 7) 上
// 看起来不需要调用 openssl_get_privatekey 或类似函数。
// 只需按上面定义的方式传递密钥即可
openssl_sign($data, $binary_signature, $private_key, OPENSSL_ALGO_SHA1);

// 校验签名
$ok = openssl_verify($data, $binary_signature, $public_key, OPENSSL_ALGO_SHA1);
echo
"校验 #1: ";
if (
$ok == 1) {
echo
"签名正确 (应该如此)\n";
} elseif (
$ok == 0) {
echo
"签名错误 (存在问题)\n";
} else {
echo
"错误,签名校验失败\n";
}

$ok = openssl_verify('篡改'.$data, $binary_signature, $public_key, OPENSSL_ALGO_SHA1);
echo
"校验 #2: ";
if (
$ok == 1) {
echo
"错误:数据已被篡改,但签名仍然有效!糟糕!\n";
} elseif (
$ok == 0) {
echo
"签名错误 (应该如此,因为数据已被篡改)\n";
} else {
echo
"错误,签名校验失败\n";
}

?>
tim at remitone dot com
1年前
需要注意的是,`openssl_sign()` 和 `openssl_verify` 使用的默认签名算法 (OPENSSL_ALGO_SHA1) 在 OpenSSL 3 系列版本中不再默认支持。

对于更新的 OpenSSL 库,需要在服务器上运行以下命令:
“`update-crypto-policies --set LEGACY`”
这样才能在不使用可选的替代算法参数的情况下使这些函数正常工作。
To Top