(self, key, value)
Parse a status code from the attached GnuPG process.

        :raises: :exc:`~exceptions.ValueError` if the status message is unknown.
Parse a status code from the attached GnuPG process.
Parse a status code from the attached GnuPG process .
def _handle_status(self, key, value):
        """Parse a status code from the attached GnuPG process.

        :raises: :exc:`~exceptions.ValueError` if the status message is unknown.
        """
        if key in self.TRUST_LEVELS:
            self.trust_text = key
            self.trust_level = self.TRUST_LEVELS[key]
        elif key in (
                "RSA_OR_IDEA",
                "NODATA",
                "IMPORT_RES",
                "PLAINTEXT",
                "PLAINTEXT_LENGTH",
                "POLICY_URL",
                "DECRYPTION_INFO",
                "DECRYPTION_KEY",
                "DECRYPTION_OKAY",
                "INV_SGNR",
                "PROGRESS",
                "PINENTRY_LAUNCHED",
                "SUCCESS",
                "UNEXPECTED",
                "ENCRYPTION_COMPLIANCE_MODE",
                "VERIFICATION_COMPLIANCE_MODE",
            ):
            pass
        elif key == "KEY_CONSIDERED":
            self.status = '\n'.join([self.status, "key considered"])
        elif key == "NEWSIG":
            # Reset
            self.status = None
            self.valid = False
            self.key_id, self.username = None, None
        elif key == "BADSIG":
            self.valid = False
            self.status = 'signature bad'
            self.key_id, self.username = value.split(None, 1)
        elif key == "GOODSIG":
            self.valid = True
            self.status = 'signature good'
            self.key_id, self.username = value.split(None, 1)
        elif key == "VALIDSIG":
            self.valid = True
            (self.fingerprint,
             self.creation_date,
             self.sig_timestamp,
             self.expire_timestamp) = value.split()[:4]
            # may be different if signature is made with a subkey
            self.pubkey_fingerprint = value.split()[-1]
            self.status = 'signature valid'
        elif key == "SIG_ID":
            (self.signature_id,
             self.creation_date, self.timestamp) = value.split()
        elif key == "ERRSIG":
            self.valid = False
            (self.key_id,
             algo, hash_algo,
             cls,
             self.timestamp) = value.split()[:5]
            self.status = 'signature error'
        elif key == "DECRYPTION_FAILED":
            self.valid = False
            self.key_id = value
            self.status = 'decryption failed'
        elif key in ("WARNING", "ERROR", "FAILURE"):
            if key in ("ERROR", "FAILURE"):
                self.valid = False
            # The status will hold a (rather indecipherable and bad
            # design, imho) location (in the GnuPG C code), GnuPG
            # error_code, e.g. "151011327_EOF", and (possibly, in the
            # case of WARNING or ERROR) additional text.
            # Have fun figuring out what it means.
            self.status = value
            log.warn("%s status emitted from gpg process: %s" % (key, value))
        elif key == "NO_PUBKEY":
            self.valid = False
            self.key_id = value
            self.status = 'no public key'
        # These are useless in Verify, since they are spit out for any
        # pub/subkeys on the key, not just the one doing the signing.
        # if we want to check for signatures make with expired key,
        # the relevant flags are REVKEYSIG and KEYREVOKED.
        elif key in ("KEYEXPIRED", "SIGEXPIRED"):
            pass
        # The signature has an expiration date which has already passed
        # (EXPKEYSIG), or the signature has been revoked (REVKEYSIG):
        elif key in ("EXPKEYSIG", "REVKEYSIG"):
            self.valid = False
            self.key_id = value.split()[0]
            self.status = (('%s %s') % (key[:3], key[3:])).lower()
        # This is super annoying, and bad design on the part of GnuPG, in my
        # opinion.
        #
        # This flag can get triggered if a valid signature is made, and then
        # later the key (or subkey) which created the signature is
        # revoked. When this happens, GnuPG will output:
        #
        # REVKEYSIG 075BFD18B365D34C Test Expired Key <test@python-gnupg.git>
        # VALIDSIG DAB69B05F591640B7F4DCBEA075BFD18B365D34C 2014-09-26 1411700539 0 4 0 1 2 00 4BA800F77452A6C29447FF20F4AF76ACBBE22CE2
        # KEYREVOKED
        #
        # Meaning that we have a timestamp for when the signature was created,
        # and we know that the signature is valid, but since GnuPG gives us no
        # timestamp for when the key was revoked... we have no ability to
        # determine if the valid signature was made *before* the signing key
        # was revoked or *after*. Meaning that if you are like me and you sign
        # all your software releases and git commits, and you also practice
        # good opsec by doing regular key rotations, your old signatures made
        # by your expired/revoked keys (even though they were created when the
        # key was still good) are considered bad because GnuPG is a
        # braindamaged piece of shit.
        #
        # Software engineering, motherfuckers, DO YOU SPEAK IT?
        #
        # The signing key which created the signature has since been revoked
        # (KEYREVOKED), and we're going to ignore it (but add something to the
        # status message):
        elif key in ("KEYREVOKED"):
            self.status = '\n'.join([self.status, "key revoked"])
        # SIG_SUBPACKET <type> <flags> <len> <data>
        # This indicates that a signature subpacket was seen.  The format is
        # the same as the "spk" record above.
        #
        # [...]
        #
        # SPK - Signature subpacket records
        #
        # - Field 2 :: Subpacket number as per RFC-4880 and later.
        # - Field 3 :: Flags in hex.  Currently the only two bits assigned
        #              are 1, to indicate that the subpacket came from the
        #              hashed part of the signature, and 2, to indicate the
        #              subpacket was marked critical.
        # - Field 4 :: Length of the subpacket.  Note that this is the
        #              length of the subpacket, and not the length of field
        #              5 below.  Due to the need for %-encoding, the length
        #              of field 5 may be up to 3x this value.
        # - Field 5 :: The subpacket data.  Printable ASCII is shown as
        #              ASCII, but other values are rendered as %XX where XX
        #              is the hex value for the byte.
        elif key in ("SIG_SUBPACKET"):
            fields = value.split()
            try:
                subpacket_number = fields[0]
                self.subpackets[subpacket_number] = {'flags': None,
                                                     'length': None,
                                                     'data': None}
            except IndexError:
                # We couldn't parse the subpacket type (an RFC4880
                # identifier), so we shouldn't continue parsing.
                pass
            else:
                # Pull as much data as we can parse out of the subpacket:
                try:
                    self.subpackets[subpacket_number]['flags'] = fields[1]
                    self.subpackets[subpacket_number]['length'] = fields[2]
                    self.subpackets[subpacket_number]['data'] = fields[3]
                except IndexError:
                    pass
        # NOTATION_
        # There are actually two related status codes to convey notation
        # data:
        #
        # - NOTATION_NAME <name>
        # - NOTATION_DATA <string>
        #
        # <name> and <string> are %XX escaped; the data may be split among
        # several NOTATION_DATA lines.
        elif key.startswith("NOTATION_"):
            if key.endswith("NAME"):
                self.notations[value] = str()
                self._last_notation_name = value
            elif key.endswith("DATA"):
                if self._last_notation_name is not None:
                    # Append the NOTATION_DATA to any previous data we
                    # received for that NOTATION_NAME:
                    self.notations[self._last_notation_name] += value
                else:
                    pass
        else:
            raise ValueError("Unknown status message: %r %r" % (key, value))
def _handle_status ( self , key , value ) : if key in self . TRUST_LEVELS : self . trust_text = key self . trust_level = self . TRUST_LEVELS [ key ] elif key in ( "RSA_OR_IDEA" , "NODATA" , "IMPORT_RES" , "PLAINTEXT" , "PLAINTEXT_LENGTH" , "POLICY_URL" , "DECRYPTION_INFO" , "DECRYPTION_KEY" , "DECRYPTION_OKAY" , "INV_SGNR" , "PROGRESS" , "PINENTRY_LAUNCHED" , "SUCCESS" , "UNEXPECTED" , "ENCRYPTION_COMPLIANCE_MODE" , "VERIFICATION_COMPLIANCE_MODE" , ) : pass elif key == "KEY_CONSIDERED" : self . status = '\n' . join ( [ self . status , "key considered" ] ) elif key == "NEWSIG" : # Reset self . status = None self . valid = False self . key_id , self . username = None , None elif key == "BADSIG" : self . valid = False self . status = 'signature bad' self . key_id , self . username = value . split ( None , 1 ) elif key == "GOODSIG" : self . valid = True self . status = 'signature good' self . key_id , self . username = value . split ( None , 1 ) elif key == "VALIDSIG" : self . valid = True ( self . fingerprint , self . creation_date , self . sig_timestamp , self . expire_timestamp ) = value . split ( ) [ : 4 ] # may be different if signature is made with a subkey self . pubkey_fingerprint = value . split ( ) [ - 1 ] self . status = 'signature valid' elif key == "SIG_ID" : ( self . signature_id , self . creation_date , self . timestamp ) = value . split ( ) elif key == "ERRSIG" : self . valid = False ( self . key_id , algo , hash_algo , cls , self . timestamp ) = value . split ( ) [ : 5 ] self . status = 'signature error' elif key == "DECRYPTION_FAILED" : self . valid = False self . key_id = value self . status = 'decryption failed' elif key in ( "WARNING" , "ERROR" , "FAILURE" ) : if key in ( "ERROR" , "FAILURE" ) : self . valid = False # The status will hold a (rather indecipherable and bad # design, imho) location (in the GnuPG C code), GnuPG # error_code, e.g. "151011327_EOF", and (possibly, in the # case of WARNING or ERROR) additional text. # Have fun figuring out what it means. self . status = value log . warn ( "%s status emitted from gpg process: %s" % ( key , value ) ) elif key == "NO_PUBKEY" : self . valid = False self . key_id = value self . status = 'no public key' # These are useless in Verify, since they are spit out for any # pub/subkeys on the key, not just the one doing the signing. # if we want to check for signatures make with expired key, # the relevant flags are REVKEYSIG and KEYREVOKED. elif key in ( "KEYEXPIRED" , "SIGEXPIRED" ) : pass # The signature has an expiration date which has already passed # (EXPKEYSIG), or the signature has been revoked (REVKEYSIG): elif key in ( "EXPKEYSIG" , "REVKEYSIG" ) : self . valid = False self . key_id = value . split ( ) [ 0 ] self . status = ( ( '%s %s' ) % ( key [ : 3 ] , key [ 3 : ] ) ) . lower ( ) # This is super annoying, and bad design on the part of GnuPG, in my # opinion. # # This flag can get triggered if a valid signature is made, and then # later the key (or subkey) which created the signature is # revoked. When this happens, GnuPG will output: # # REVKEYSIG 075BFD18B365D34C Test Expired Key <test@python-gnupg.git> # VALIDSIG DAB69B05F591640B7F4DCBEA075BFD18B365D34C 2014-09-26 1411700539 0 4 0 1 2 00 4BA800F77452A6C29447FF20F4AF76ACBBE22CE2 # KEYREVOKED # # Meaning that we have a timestamp for when the signature was created, # and we know that the signature is valid, but since GnuPG gives us no # timestamp for when the key was revoked... we have no ability to # determine if the valid signature was made *before* the signing key # was revoked or *after*. Meaning that if you are like me and you sign # all your software releases and git commits, and you also practice # good opsec by doing regular key rotations, your old signatures made # by your expired/revoked keys (even though they were created when the # key was still good) are considered bad because GnuPG is a # braindamaged piece of shit. # # Software engineering, motherfuckers, DO YOU SPEAK IT? # # The signing key which created the signature has since been revoked # (KEYREVOKED), and we're going to ignore it (but add something to the # status message): elif key in ( "KEYREVOKED" ) : self . status = '\n' . join ( [ self . status , "key revoked" ] ) # SIG_SUBPACKET <type> <flags> <len> <data> # This indicates that a signature subpacket was seen.  The format is # the same as the "spk" record above. # # [...] # # SPK - Signature subpacket records # # - Field 2 :: Subpacket number as per RFC-4880 and later. # - Field 3 :: Flags in hex.  Currently the only two bits assigned #              are 1, to indicate that the subpacket came from the #              hashed part of the signature, and 2, to indicate the #              subpacket was marked critical. # - Field 4 :: Length of the subpacket.  Note that this is the #              length of the subpacket, and not the length of field #              5 below.  Due to the need for %-encoding, the length #              of field 5 may be up to 3x this value. # - Field 5 :: The subpacket data.  Printable ASCII is shown as #              ASCII, but other values are rendered as %XX where XX #              is the hex value for the byte. elif key in ( "SIG_SUBPACKET" ) : fields = value . split ( ) try : subpacket_number = fields [ 0 ] self . subpackets [ subpacket_number ] = { 'flags' : None , 'length' : None , 'data' : None } except IndexError : # We couldn't parse the subpacket type (an RFC4880 # identifier), so we shouldn't continue parsing. pass else : # Pull as much data as we can parse out of the subpacket: try : self . subpackets [ subpacket_number ] [ 'flags' ] = fields [ 1 ] self . subpackets [ subpacket_number ] [ 'length' ] = fields [ 2 ] self . subpackets [ subpacket_number ] [ 'data' ] = fields [ 3 ] except IndexError : pass # NOTATION_ # There are actually two related status codes to convey notation # data: # # - NOTATION_NAME <name> # - NOTATION_DATA <string> # # <name> and <string> are %XX escaped; the data may be split among # several NOTATION_DATA lines. elif key . startswith ( "NOTATION_" ) : if key . endswith ( "NAME" ) : self . notations [ value ] = str ( ) self . _last_notation_name = value elif key . endswith ( "DATA" ) : if self . _last_notation_name is not None : # Append the NOTATION_DATA to any previous data we # received for that NOTATION_NAME: self . notations [ self . _last_notation_name ] += value else : pass else : raise ValueError ( "Unknown status message: %r %r" % ( key , value ) )