【问题标题】:What do returned values of PHP gnupg signature verification mean?PHP gnupg 签名验证的返回值是什么意思?
【发布时间】:2015-09-25 16:47:34
【问题描述】:

我想验证 PHP 中的 pgp 签名文本。按照 PHP 文档和对this 问题的回答,我制作了简单的脚本来测试 gnupg 库。我使用 Thunderbird 和 Enigmail 在两个电子邮件帐户之间发送了签名的电子邮件 - 接收到 Thunderbird 表明签名是正确的。

在 PHP 中,当我使用纯电子邮件文本和发件人公钥时,verify() 函数返回如下数组:

array(1) {
  [0]=>
  array(5) {
    ["fingerprint"]=>
    string(40) "468F82339FC55DE5CAFD71BB63DD32AE1308A57F"
    ["validity"]=>
    int(0)
    ["timestamp"]=>
    int(1443033896)
    ["status"]=>
    int(0)
    ["summary"]=>
    int(0)
  }
}

当我更改签名消息单个单词时,结果更改为:

array(1) {
  [0]=>
  array(5) {
    ["fingerprint"]=>
    string(16) "63DD32AE1308A57F"
    ["validity"]=>
    int(0)
    ["timestamp"]=>
    int(0)
    ["status"]=>
    int(117440520)
    ["summary"]=>
    int(4)
  }
}

最后,当我更改大量文本或破坏签名时,函数返回false

那么,这些数组值是什么意思呢?

  • 为什么validity 总是0
  • timestamp 值是什么时间戳?消息签署的时间?
  • 为什么在第二种情况下status 的值这么大?它只是随机值还是特定的错误代码?
  • summary 相同,4 的价值是什么?

如果我只想简单地识别文本是否正确签名,我可以将返回的fingerprint 与公钥指纹进行比较,然后检查状态和摘要是否等于0

【问题讨论】:

    标签: php gnupg pgp


    【解决方案1】:

    PHP 的 GnuPG 文档在这里确实缺少信息。查看source code和GPGME手册和来源,可以得出相关信息。

    免责声明:答案包含一些猜测,如果在此基础上构建,请务必对正在发生的事情有合理的感觉,并随时提供反馈! p>

    有效期

    为什么有效性总是 0?

    为了验证签名的validity,您需要分配信任(因此 GnuPG 能够计算信任链)。 validity is defined in following GPGME enums

    /* The available validities for a trust item or key.  */
    typedef enum
      {
        GPGME_VALIDITY_UNKNOWN   = 0,
        GPGME_VALIDITY_UNDEFINED = 1,
        GPGME_VALIDITY_NEVER     = 2,
        GPGME_VALIDITY_MARGINAL  = 3,
        GPGME_VALIDITY_FULL      = 4,
        GPGME_VALIDITY_ULTIMATE  = 5
      }
    gpgme_validity_t;
    

    时间戳

    timestamp 值是什么时间戳?消息签署的时间?

    是的,这很简单,这是签名创建时间戳。请注意,时间戳通常由签名者定义,并且可以伪造为任意日期。

    状态

    与摘要相同,4 代表什么?

    阅读documentation (gpgme_error_t status),似乎状态是在gpg-error.h 中定义的。这是very long list hosted in GnuPG's git repository

    但是,您问题中定义的状态对我来说没有意义。

    总结

    为什么在第二种情况下状态值这么大?它只是随机值还是特定的错误代码?

    这是关于签名的摘要。同样,summary is defined in a GPGME enum

    /* Flags used for the SUMMARY field in a gpgme_signature_t.  */
    typedef enum
      {
        GPGME_SIGSUM_VALID       = 0x0001,  /* The signature is fully valid.  */
        GPGME_SIGSUM_GREEN       = 0x0002,  /* The signature is good.  */
        GPGME_SIGSUM_RED         = 0x0004,  /* The signature is bad.  */
        GPGME_SIGSUM_KEY_REVOKED = 0x0010,  /* One key has been revoked.  */
        GPGME_SIGSUM_KEY_EXPIRED = 0x0020,  /* One key has expired.  */
        GPGME_SIGSUM_SIG_EXPIRED = 0x0040,  /* The signature has expired.  */
        GPGME_SIGSUM_KEY_MISSING = 0x0080,  /* Can't verify: key missing.  */
        GPGME_SIGSUM_CRL_MISSING = 0x0100,  /* CRL not available.  */
        GPGME_SIGSUM_CRL_TOO_OLD = 0x0200,  /* Available CRL is too old.  */
        GPGME_SIGSUM_BAD_POLICY  = 0x0400,  /* A policy was not met.  */
        GPGME_SIGSUM_SYS_ERROR   = 0x0800   /* A system error occured.  */
      }
    gpgme_sigsum_t;
    

    因此,您必须将结果作为二进制标志读取。状态 4 表示签名错误。

    总结

    第一个签名是几天前在 2015-09-23T18:44:56+00:00 由密钥 468F82339FC55DE5CAFD71BB63DD32AE1308A57F 生成的,并且是正确的签名,但可以验证密钥(缺少信任路径)。

    第二个签名似乎是由同一个密钥发出的,但已损坏。

    如果我只想简单地识别文本是否正确签名,我可以将返回的指纹与公钥指纹进行比较,然后检查状态和摘要是否等于 0?

    据我了解,您应该测试summary 的第 4 位是否已设置。如果已设置,则您的签名不正确。不要和4比较,而是使用位操作来测试单个位:

    ($summary & 0x04) == 0x04
    

    如果您不使用信任网络和validity 标志来验证签名,请确保将整个指纹与受信任的密钥列表进行比较。

    【讨论】:

      猜你喜欢
      • 2013-04-25
      • 2014-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多