如何在 PHP 中对文件进行数字签名

Posted

技术标签:

【中文标题】如何在 PHP 中对文件进行数字签名【英文标题】:how to digitally sign a file in PHP 【发布时间】:2012-03-14 18:20:55 【问题描述】:

我在我的数据库中创建了一个 user 表,其中包含用于保存用户信息的不同列。我还添加了两列 public_keyprivate_key。 当用户注册时,他的信息将被插入到表中。另外我正在使用:

// Create the keypair
$res=openssl_pkey_new();

// Get private key
openssl_pkey_export($res, $privatekey);

// Get public key
$publickey=openssl_pkey_get_details($res);
$publickey=$publickey["key"];

创建一个随机密钥对并将其提供给用户,以便每个用户都有一个密钥对。 我希望我的用户具有数字签名能力,所以当他们上传文件时,他们会对其进行签名。

我决定先签署一个示例文件(msg.txt),看看是否可以,然后继续。它看起来直截了当:

openssl_pkcs7_sign("msg.txt", "signed.txt", "signing_cert.pem",
array("private_key.pem", "mypassphrase"),
array()
);

问题是:signing_cert.pem 和 private_key.pem 是什么?我将生成的公钥粘贴到了signing_cert.pem 中,将私有密钥粘贴到了private_key.pem 中,但是我看到了这个错误:

Warning: openssl_pkcs7_sign() [function.openssl-pkcs7-sign]: error getting 
private key in /home/ofathian/public_html/msc/ebook/mine/assymetric-test.php 
on line 40

欢迎提出任何意见。

【问题讨论】:

【参考方案1】:

我得出了为什么不自己制作数字签名功能的结论。

数字签名算法的工作原理如下: 首先对纯文本进行散列,然后由用户的私钥加密,然后是结果 与纯文本连接。

伪代码:

return [input + encrypt(md5(input),private_key)]

用于验证:输入被拆分为纯文本和签名。然后签名被解密 使用公钥。然后将结果与纯文本的哈希值进行比较,如果它们 相等表示签名已验证。

伪代码:

explode(input) --> plain_text , signature
if( decrypt(signature,public_key) == md5(plain_text) ) then signature is trusted

现在是我测试过并正在使用的真正 PHP 代码:

function sign($cleartext,$private_key)

    $msg_hash = md5($cleartext);
    openssl_private_encrypt($msg_hash, $sig, $private_key);
    $signed_data = $cleartext . "----SIGNATURE:----" . $sig;
    return mysql_real_escape_string($signed_data);


function verify($my_signed_data,$public_key)

    list($plain_data,$old_sig) = explode("----SIGNATURE:----", $my_signed_data);
    openssl_public_decrypt($old_sig, $decrypted_sig, $public_key);
    $data_hash = md5($plain_data);
    if($decrypted_sig == $data_hash && strlen($data_hash)>0)
        return $plain_data;
    else
        return "ERROR -- untrusted signature";

【讨论】:

我建议只返回一个布尔值,因为这是函数名称所暗示的。 有趣,但如果----SIGNATURE:---- 出现在数据中怎么办?【参考方案2】:

signing_cert.pem 和 private_key.pem 是您用来签署该文件的证书。 因此,如果您将它们存储在 DB 中,则需要将它们分别转储到名为 signing_cert.pem 和 private_key.pem 的文件中。

您得到的错误是 openssl 尝试加载这些文件,并且由于它们不存在,因此它声称。

如果您将这些文件从数据库写入硬盘,请注意:

    请勿将其存储在任何公共可访问文件夹中(避免使用 DOCUMENT_ROOT 和临时目录)。专门用于避免安全问题的私钥。 完成后将其删除。

此外,您可以将这些证书存储在每个用户的某个文件夹中,而不是将这些证书存储在数据库中,以防止在签名时转储到文件中。当然,任何人都不能访问该文件夹。

更多信息:PHP openssl_pkc7_sign

【讨论】:

您认为我将生成的公钥粘贴到 signing_cert.pem 中,然后将私有密钥粘贴到 private_key.pem 中是否正确? signing_cert.pem 看起来像: -----BEGIN PUBLIC KEY----- zzz...zzz... -----END PUBLIC KEY----- 和 private_key .pem 看起来像: -----BEGIN RSA PRIVATE KEY----- ..z... -----END RSA PRIVATE KEY----- 在私钥文件中不应该是 DSA而不是RSA? (数字签名算法) 如果您粘贴了这些文件,请检查文件权限(下一次,请在 WWW 根目录之外进行)。 不幸的是,我对回答您最后一条评论的密钥知之甚少,不知道它是否应该 DSA,但我已经看到了许多为此目的的 RSA 签名,所以它应该可以工作适合 RSA。 我将两者的权限都更改为 0777 但没有成功

以上是关于如何在 PHP 中对文件进行数字签名的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 xcode5 在 Mac 应用程序中对捆绑的可执行文件进行代码签名

如果您可以在 7 次比较中对 5 个数字进行排序,那么如何在 10 次比较中对 6 个数字进行排序?

如何在 .net 中对 HTTPS 请求进行数字签名?

如何在 Python 中对数字的数字进行排序并获取另一个数字?

如何在 Web 应用程序中对 PDF 文档进行数字签名?

如何在javascript中对字母数字数组进行排序[重复]