如何在 PHP 中对文件进行数字签名
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9707794/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to digitally sign a file in PHP
提问by Omidoo
I made a usertable in my DB with different columns for holding users' info. Also I have added two columns public_keyand private_key. When a user registers, his info will be inserted to the table. plus I am using:
我在我的数据库中创建了一个用户表,其中包含用于保存用户信息的不同列。我还添加了两列public_key和private_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"];
to create a random key pair and give it to user so that every user has a key pair. I want my users to have digital-signature ability, so when they upload a file they sign it.
创建一个随机密钥对并将其提供给用户,以便每个用户都有一个密钥对。我希望我的用户具有数字签名能力,因此当他们上传文件时,他们会对其进行签名。
I decided to sign a sample file(msg.txt) first to see if I can and then proceed. It looks straight forward:
我决定先签署一个示例文件(msg.txt),看看我是否可以,然后继续。它看起来很直接:
openssl_pkcs7_sign("msg.txt", "signed.txt", "signing_cert.pem",
array("private_key.pem", "mypassphrase"),
array()
);
The problem is: what are signing_cert.pem and private_key.pem ? I pasted my generated public key in signing_cert.pem and the private one in private_key.pem, but I see this error:
问题是: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
Any opinion is appreciated.
任何意见表示赞赏。
回答by Omidoo
I came to conclusion of why not make my own digital signing function.
我得出了为什么不制作自己的数字签名功能的结论。
digital signing algorithm works like this: first the plain text is hashed then it is encypted by user's private key, then the result is concatenated with the plain text.
数字签名算法的工作原理是这样的:首先对纯文本进行散列,然后通过用户的私钥对其进行加密,然后将结果与纯文本连接起来。
pseudo code:
伪代码:
return [input + encrypt(md5(input),private_key)]
For verifying: Input is splitted to plain text and signature. then signature is decrypted using public key. Then the result is compared to the hash of the plain text and if they are equal it means the signature is verified.
用于验证:输入被拆分为纯文本和签名。然后使用公钥解密签名。然后将结果与纯文本的哈希值进行比较,如果它们相等,则表示签名得到验证。
pseudo code:
伪代码:
explode(input) --> plain_text , signature
if( decrypt(signature,public_key) == md5(plain_text) ) then signature is trusted
Now the real PHP code which I have tested and currently using:
现在我已经测试过并正在使用的真正的 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";
}
回答by StormByte
signing_cert.pem and private_key.pem are the certificates you use to sign that file. So if you have them stored in DB, you need to dump them to files called signing_cert.pem and private_key.pem respectivelly.
signing_cert.pem 和 private_key.pem 是用于签署该文件的证书。因此,如果您将它们存储在数据库中,则需要将它们分别转储到名为 signing_cert.pem 和 private_key.pem 的文件中。
The error you are getting is that openssl tries to load those files, and since they do not exists then it claims.
您收到的错误是 openssl 尝试加载这些文件,并且由于它们不存在,因此它声称。
If you write those files to harddisk from your DB, plase TAKE IN MIND:
如果您将这些文件从数据库写入硬盘,请注意:
- Do NOT store it in any public accesible folder (avoid DOCUMENT_ROOT AND temp directory). Specially for the private key to avoid security issues.
- Remove them when you've done.
- 不要将其存储在任何公共可访问文件夹中(避免 DOCUMENT_ROOT 和临时目录)。专门针对私钥,避免安全问题。
- 完成后删除它们。
Also, you could, instead of having those certificates in DB, have them stored in some folder for each user, to prevent dumping to a file when signing. Of course, that folder should not be accesible to anyone.
此外,您可以不将这些证书放在数据库中,而是将它们存储在每个用户的某个文件夹中,以防止在签名时转储到文件中。当然,任何人都不应访问该文件夹。
More info: PHP openssl_pkc7_sign