【问题标题】:Encrypt files using PGP in PHP?在 PHP 中使用 PGP 加密文件?
【发布时间】:2013-04-12 11:04:42
【问题描述】:

我想使用 PGP 加密来加密 CSV 文件,我通过 PHP 脚本生成,然后通过电子邮件将该文件发送给客户端。客户会给我加密密钥,我需要用它来加密文件。

我在 Google 上搜索了 PGP,发现它是相当好的隐私,我还发现了 OpenPGP http://www.openpgp.org/ 和 GnuPG http://www.gnupg.org/ 这两种 PGP 是什么?我应该使用哪一个?

另外,如何使用我的客户端提供的密钥在 PHP 中使用 PGP 加密文件?

我第一次听说这个术语,请任何人帮助理解它并在 PHP 中实现它。

【问题讨论】:

    标签: php pgp gnupg openpgp


    【解决方案1】:

    问题1:关于PGP

    • PGP(Pretty Good Privacy)是赛门铁克公司的产品和商标(他们几年前买的)。
    • OpenPGP 是 PGP 使用的标准。
    • GnuPG(Gnu Privacy Guard)是 PGP 的免费开源实现。

    所以你要做的是加密到一个 OpenPGP 密钥。您的客户端使用哪种 OpenPGP 实现来解密数据对您来说并不重要。 PHP一般使用GnuPG,内置接口。

    问题2:在PHP中使用GnuPG

    使用GnuPG interface,这是一个可以为 PHP 安装的扩展。

    首先,导入密钥,其中$keydata是ASCII装甲公钥:

    <?php
    $gpg = new gnupg();
    $info = $gpg -> import($keydata);
    print_r($info);
    ?>
    

    然后使用此密钥加密数据,这次使用客户端密钥的指纹:

    <?php
      $gpg = new gnupg();
      $gpg -> addencryptkey("8660281B6051D071D94B5B230549F9DC851566DC");
      $enc = $gpg -> encrypt("just a test");
      echo $enc;
    ?>
    

    如果您想加密文件,请阅读并将它们传递给encrypt()。确保在引用密钥时至少使用长密钥 ID(例如DEADBEEFDEADBEEF)、更好的指纹(如示例中);和never use short key IDs (DEADBEEF), as those are vulnerable to collision attacks


    这是一个用户在PHP手册中添加的更多comprehensive example for doing both

    【讨论】:

    • 之后我应该如何在邮件中发送这个,我是否应该简单地将 $enc 变量作为邮件正文,然后启用 PGP 的电子邮件软件将能够自己读取它?或者怎么做才能通过邮件发送?
    • 您想将加密文件作为附件发送还是加密整个邮件?
    • 我不确定客户是否说用 PGP 加密文件并通过邮件发送。
    • 澄清:addencryptkey 需要指纹。您可以通过gpg –fingerprint {user_id}获取用户指纹。
    • 永远不要使用用户 ID,尤其是短(8 位)的。见What is an OpenPGP Key ID collision?。出于编程/脚本目的,始终存储和处理完整的指纹。用户交互可以使用长密钥 ID,如果使用短密钥 ID 进行交互,请始终警告用户并确保在未检查指纹或长 ID 的情况下不要信任任何内容。
    【解决方案2】:

    在这里留下一个答案,因为网络上的许多 PHP GnuPG 示例都是非常简单的,希望这可以节省一些人的挫败感。

    基本上,它反映了 GnuPG 命令行工具的工作方式。如果密钥不在 gpg 的密钥环中,则需要导入密钥,然后您需要选择收件人的密钥以用于加密/解密。

    gpg --import recipients-public-key.asc
    gpg -r recipient --encrypt test.txt
    

    如果你做了我做的事情并作为接收者传递了密钥,它就行不通了!

    不清楚GPG manualPHP documentation 中的这个字段是什么,将这个字段称为“指纹”。检查 gpg 的密钥环以获取您新导入的密钥:

    gpg --list-keys
    

    这将输出如下内容:

    pub   rsa2048 2019-04-14 [SC] [expires: 2021-04-14]
          0DAA2C747B1974BE9EB9E6DCF7EE249AD00A46AA
    uid           [ultimate] Dean Or
    sub   rsa2048 2019-04-14 [E] [expires: 2021-04-14]
    

    这将为您提供 UID,并在第二行提供与每个键关联的指纹。 据我所知,您可以使用 UID 和指纹作为收件人。

    所以您要加密的 PHP 代码可能如下所示:

    // Encrypt
    $gpg = new gnupg();
    $gpg->seterrormode(gnupg::ERROR_EXCEPTION);
    
    // Check key ring for recipient public key, otherwise import it
    $keyInfo = $gpg->keyinfo('0DAA2C747B1974BE9EB9E6DCF7EE249AD00A46AA');
    if (empty($keyInfo)) {
        $gpg->import('recipients-public-key.asc');
    }
    $gpg->addencryptkey('0DAA2C747B1974BE9EB9E6DCF7EE249AD00A46AA');
    echo $gpg->encrypt('This is a test!');
    

    那么收件人的代码将如下所示:

    // Decrypt
    $gpg = new gnupg();
    $gpg->seterrormode(gnupg::ERROR_EXCEPTION);
    
    // Check key ring for recipient private key, otherwise import it
    $keyInfo = $gpg->keyinfo('0DAA2C747B1974BE9EB9E6DCF7EE249AD00A46AA');
    if (empty($keyInfo)) {
        $gpg->import('recipients-private-key.asc');
    }
    $gpg->adddecryptkey('0DAA2C747B1974BE9EB9E6DCF7EE249AD00A46AA', '');
    echo $gpg->decrypt($encyptedMessage);
    

    请注意,收件人的公钥和私钥的指纹相同。

    还有一个已知问题 adddecryptkey 不使用密码!您需要删除密码或更改您的 GnuPG 版本。

    【讨论】:

    • 我也尝试过 csv 文件加密,但没有得到任何解决方案。我的要求是加密 CSV 文件并放入 SFTP。在 php 中我们只能做消息级加密。
    猜你喜欢
    • 1970-01-01
    • 2023-03-17
    • 2020-01-17
    • 2018-05-22
    • 1970-01-01
    • 2017-04-09
    • 1970-01-01
    • 2011-05-12
    • 1970-01-01
    相关资源
    最近更新 更多