问题
I want to verify pgp signed text in PHP. Following PHP documentation and answer to this question i made simple script to test gnupg library. I sent signed email between two email accounts using Thunderbird with Enigmail - receiving Thunderbird shows that signature is correct.
In PHP, when i use plain email text and senders public key, verify()
function returns array like this:
array(1) {
[0]=>
array(5) {
["fingerprint"]=>
string(40) "468F82339FC55DE5CAFD71BB63DD32AE1308A57F"
["validity"]=>
int(0)
["timestamp"]=>
int(1443033896)
["status"]=>
int(0)
["summary"]=>
int(0)
}
}
When i change in signed message single word, result changes to:
array(1) {
[0]=>
array(5) {
["fingerprint"]=>
string(16) "63DD32AE1308A57F"
["validity"]=>
int(0)
["timestamp"]=>
int(0)
["status"]=>
int(117440520)
["summary"]=>
int(4)
}
}
And finally, when i change a lot of text or broke signature, function returns false
.
So, what do these array values mean?
- Why
validity
is always0
? timestamp
value is a timestamp of what? Time when message was signed?- Why
status
value is so big in second case? Its just random value or specific error code? - Same with
summary
what stands value of4
for?
If i want to just simply recognize if text is signed correctly or not, can i just compare returned fingerprint
with fingerprint of public key and check if status and summary are equal to 0
?
回答1:
PHP's GnuPG documentation is indeed lacking information here. Looking at the source code and GPGME manual and sources, you can derive the relevant information.
Disclaimer: The answer contains some guesswork, by sure to get a reasonable feeling about what's going on if building on it, and feel free to give feedback!
Validity
Why validity is always 0?
For verifying the validity
of a signature, you need to assign trust (so GnuPG is able to compute a trust chain). The 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
timestamp value is a timestamp of what? Time when message was signed?
Yes, this one's easy, this is the signature creation timestamp. Be aware the timestamp is usually defined by the signer and can be faked to arbitrary dates.
Status
Same with summary what stands value of 4 for?
Reading the documentation (gpgme_error_t status), it seems the status is defined in gpg-error.h
. This is a very long list hosted in GnuPG's git repository.
Yet, the defined status in your question does not make sense to me.
Summary
Why status value is so big in second case? Its just random value or specific error code?
This is a summary on the signature. Again, the 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;
Thus, you've got to read the result as binary flags. A status of 4 indicates a bad signature.
Wrap-Up
The first signature was generated some days ago on 2015-09-23T18:44:56+00:00 by key 468F82339FC55DE5CAFD71BB63DD32AE1308A57F
and is a correct signature, but the key could be validated (missing trust path).
The second signature seems to be issued by the same key, but is broken.
If i want to just simply recognize if text is signed correctly or not, can i just compare returned fingerprint with fingerprint of public key and check if status and summary are equal to 0?
As far as I understand what's going on, you should test whether summary
's bit 4 is set or not. If it is set, you've got a bad signature. Don't compare it with 4, but use bit manipulation to test against the single bit:
($summary & 0x04) == 0x04
If you don't use the web of trust and validity
flag to verify signatures, make sure to compare the whole fingerprint against a list of trusted keys.
来源:https://stackoverflow.com/questions/32787007/what-do-returned-values-of-php-gnupg-signature-verification-mean