parameters: (signed, key, **kw)
docstring: Check a signed message against the appropriate public key.
  
      :Parameters:
          - `signed`: signed message instance, or tuple ([list of signature
            packets], corresponding message) representing a detached signature
            (or list of signatures) on a particular message
          - `key`: key to verify against (public key)
  
      :Keywords:
          - `revocs`: list (probably empty) to which all pending foreign
            revocation signature packets will be appended (see `verify_block()`)
          - `signer_fprint`: fingerprint of signing key - use this to force
            validation against a particular key packet in `key`
  
      :Returns: message that was verified (packet instance, message instance, or
          string) or None if nothing was verified
  
      All signatures in a signed message (`signed`) are verified against a key
      message (`key`). All signatures made by `key` must succeed **and** at least
      one signature must succeed in order to return True. Unassigned signatures
      in a signed message are also checked against the key message: failures pass
      silently but a successful unassigned signature contributes to verification.
  
      A successful signature verifies algorithmically against a *valid* key in
      the specified signing key. 'valid' means that the signing key is properly
      bound to the primary key (if it is not the primary key itself) and has not
      been revoked locally (at any time, for any reason).
  
      Because this function verifies against only one signing key, it is
      impossible to verify (in the same step) any applicable foreign revocations
      on that signing key message. Therefore, *foreign revocations do not figure
      into the final verdict*. Instead, they are made available as loose ends to
      be resolved elsewhere via `revocs`.
  
      Grey matter: revocations and key validity
      -----------------------------------------
      The verified signed message definition is cautious, unambiguous, and easy
      to implement: verification of all signatures made by a revoked key will
      fail. This blantantly disregards two common aspects of revocation: the time
      at which the revocation was issued and the reason for the revocation. The
      rationale is that keys which have been revoked for any reason cannot be
      assumed to enjoy the same degree of security that valid, "live" keys do.
  
      Timestamps and revocation reasons are standard notations and no more than
      standard notations.
  
      Verifying key message signatures
      --------------------------------
      Signatures *within* a key message can be verified as detached signatures::
  
          verify_msg(([sigpkt1, ..], signed_key), signing_key)
  
      ..where the list of signature packets (``sigpkt1``, etc.) must be a list of
      signatures already in ``signed_key``. When verifying self-signatures, use
      the same instance for both the ``signed_key`` and the ``signing_key``.
  
      Unfortunately, in order to cover the possibility that the signature packet
      *instances* are not the same instances in the key, signatures are matched
      by raw string value.
  
      Standalone signatures
      ---------------------
      Standalone signatures can be verified by passing them as a detached
      signature with no target message::
  
          ([sigpkt], None)
  
      :note: This function does not address verification of key messages as a
          whole since the same thing can (and would be) accomplished using
          successive calls to `verify_block()`.
      :note: Because of the interpretation of 'verified', it is not possible to
          positively (return True) verify a local primary revocation packet
          because the signing block will verify False. The focus here with
          respect to 'validity' is on the effects of the signature packets
          (rather, the existence of "negative effects") rather than just the
          algorithmic validity of them.
  
      :todo: As is, signatures are verified against an entire key message and a
          particular key in that key message cannot be singled out for
          verification
docstring_summary: Check a signed message against the appropriate public key.
docstring_tokens: Check a signed message against the appropriate public key .
function: def verify_msg(signed, key, **kw):
      """Check a signed message against the appropriate public key.
  
      :Parameters:
          - `signed`: signed message instance, or tuple ([list of signature
            packets], corresponding message) representing a detached signature
            (or list of signatures) on a particular message
          - `key`: key to verify against (public key)
  
      :Keywords:
          - `revocs`: list (probably empty) to which all pending foreign
            revocation signature packets will be appended (see `verify_block()`)
          - `signer_fprint`: fingerprint of signing key - use this to force
            validation against a particular key packet in `key`
  
      :Returns: message that was verified (packet instance, message instance, or
          string) or None if nothing was verified
  
      All signatures in a signed message (`signed`) are verified against a key
      message (`key`). All signatures made by `key` must succeed **and** at least
      one signature must succeed in order to return True. Unassigned signatures
      in a signed message are also checked against the key message: failures pass
      silently but a successful unassigned signature contributes to verification.
  
      A successful signature verifies algorithmically against a *valid* key in
      the specified signing key. 'valid' means that the signing key is properly
      bound to the primary key (if it is not the primary key itself) and has not
      been revoked locally (at any time, for any reason).
  
      Because this function verifies against only one signing key, it is
      impossible to verify (in the same step) any applicable foreign revocations
      on that signing key message. Therefore, *foreign revocations do not figure
      into the final verdict*. Instead, they are made available as loose ends to
      be resolved elsewhere via `revocs`.
  
      Grey matter: revocations and key validity
      -----------------------------------------
      The verified signed message definition is cautious, unambiguous, and easy
      to implement: verification of all signatures made by a revoked key will
      fail. This blantantly disregards two common aspects of revocation: the time
      at which the revocation was issued and the reason for the revocation. The
      rationale is that keys which have been revoked for any reason cannot be
      assumed to enjoy the same degree of security that valid, "live" keys do.
  
      Timestamps and revocation reasons are standard notations and no more than
      standard notations.
  
      Verifying key message signatures
      --------------------------------
      Signatures *within* a key message can be verified as detached signatures::
  
          verify_msg(([sigpkt1, ..], signed_key), signing_key)
  
      ..where the list of signature packets (``sigpkt1``, etc.) must be a list of
      signatures already in ``signed_key``. When verifying self-signatures, use
      the same instance for both the ``signed_key`` and the ``signing_key``.
  
      Unfortunately, in order to cover the possibility that the signature packet
      *instances* are not the same instances in the key, signatures are matched
      by raw string value.
  
      Standalone signatures
      ---------------------
      Standalone signatures can be verified by passing them as a detached
      signature with no target message::
  
          ([sigpkt], None)
  
      :note: This function does not address verification of key messages as a
          whole since the same thing can (and would be) accomplished using
          successive calls to `verify_block()`.
      :note: Because of the interpretation of 'verified', it is not possible to
          positively (return True) verify a local primary revocation packet
          because the signing block will verify False. The focus here with
          respect to 'validity' is on the effects of the signature packets
          (rather, the existence of "negative effects") rather than just the
          algorithmic validity of them.
  
      :todo: As is, signatures are verified against an entire key message and a
          particular key in that key message cannot be singled out for
          verification
      """
      saplog = logging.getLogger("saplog")
      signer_fprint = kw.get('signer_fprint', None)
      success = False # the goal is to set this to True
      opts = {}
      pending, revocs = [], []
  
      # package pending verifications, sigs & msg are verified, msg is returned
      if isinstance(signed, tuple):
          sigs, msg = signed
  
          if hasattr(msg, 'type') and msg.type in MSG_KEYS:
              opts['primary'] = msg._b_primary.leader
              blocks = msg.list_blocks()
  
              for sig in sigs: # match the sig with the appropriate block leader
  
                  for b in blocks: # may as well skip block leaders ([1:])
                      # there should be a better way to match, see func docs
                      if [s for s in b.seq()[1:] if s.rawstr() == sig.rawstr()]:
                          pending.append((sig, b.leader))
                          break
  
              if not pending:
                  raise PGPError("No matching signatures in the key message.")
  
          else:
  
              if hasattr(msg, 'type') and MSG_SIGNED == msg.type:
                  # assume the sig is singled out for verification
                  msg = msg.msg
  
              for sig in sigs: # handles all other messages and None (standalone)
                  pending.append((sig, msg))
  
      elif signed.type == MSG_SIGNED: # should be a SignedMsg
          sigs, msg = signed.sigs, signed.msg
  
          for sig in sigs:
              pending.append((sig, msg))
  
      else:
          raise NotImplementedError("Unable to verify %s." % signed)
  
      assigned = ex_verified = im_verified = 0 # Explicit/implicit verification..
      # ..is needed so that all assigned signatures are accounted for by explicit
      # verification and that implicit verification does not excuse failures for
      # assigned signatures. It's not used for much now, could use for nice logs.
  
      # verify all pending
      for sig, target in pending:
          keypkt = None
          signer_id = sig.body.keyid
  
          if signer_fprint: # forced a signer to verify against
              keypkt = key.get_keypkt(signer_fprint)
              signer_id = signer_fprint # this is ugly: it's used to match up the
              # packet and ID in the 'if keypt:' verify_block() part below
  
          elif signer_id in key.list_keyids(): # discover an sig-asserted signer
              keypkt = key.get_keypkt(signer_id)
  
          if keypkt: # either the sigpkt specified a key or an fprint was forced
              assigned += 1
  
              if sig.body.alg_hash not in (HASH_MD5, HASH_SHA1, HASH_SHA224, HASH_SHA256, HASH_SHA384, HASH_SHA512):
                  saplog.warn("A signature from ID:%r has an unsupported hash algorithm:%s(%s)." % (signer_id, sig.body.alg_hash, TXT.alg_hash_msg(sig.body.alg_hash)))
              elif CRYPT.verify(sig, target, keypkt, **opts):
                  saplog.info("Verified a signature from ID:%r." % signer_id)
                  ex_verified += 1
  
                  if _cmp_expiration(sig, SIGSUB_EXPIRES): # if sig expired..
                          saplog.info("..but the signature has expired.") #..abort
  
                  elif verify_block(key, 'key', signer_id, revocs=revocs):
                      success = True
  
                  else: # room for timestamp/reason for revocation exceptions
                      pass
              else:
                  saplog.warn("A signature from ID:%r failed." % signer_id)
  
          elif not signer_id: # try to verify unassigned sig !! not just else: !!
              matches = find_keys([key], action='sign')
  
              if matches:
                  saplog.warn("Attempting to verify an unassigned signature.")
  
                  for keyid in matches[0][1]:
                      keypkt = key.get_keypkt(keyid)
                      v = False
  
                      try:
                          v = CRYPT.verify(sig, target, keypkt, **opts)
                      except PGPCryptoError:
                          pass # this doesn't have to verify
  
                      if v:
                          im_verified += 1
  
                          if verify_block(key, 'key', keyid, revocs=revocs):
                              success = True
  
      #if 0 == assigned:
      #    saplog.warn("No matching key ID was found in key %r." % key.primary_id)
  
      if revocs and 'revocs' in kw:
          kw['revocs'].extend(revocs)
  
      if True == success:
  
          # if everything assigned was verified OR it verified as unassigned
          if (assigned and assigned == ex_verified) or im_verified:
              return msg
function_tokens: def verify_msg ( signed , key , * * kw ) : saplog = logging . getLogger ( "saplog" ) signer_fprint = kw . get ( 'signer_fprint' , None ) success = False # the goal is to set this to True opts = { } pending , revocs = [ ] , [ ] # package pending verifications, sigs & msg are verified, msg is returned if isinstance ( signed , tuple ) : sigs , msg = signed if hasattr ( msg , 'type' ) and msg . type in MSG_KEYS : opts [ 'primary' ] = msg . _b_primary . leader blocks = msg . list_blocks ( ) for sig in sigs : # match the sig with the appropriate block leader for b in blocks : # may as well skip block leaders ([1:]) # there should be a better way to match, see func docs if [ s for s in b . seq ( ) [ 1 : ] if s . rawstr ( ) == sig . rawstr ( ) ] : pending . append ( ( sig , b . leader ) ) break if not pending : raise PGPError ( "No matching signatures in the key message." ) else : if hasattr ( msg , 'type' ) and MSG_SIGNED == msg . type : # assume the sig is singled out for verification msg = msg . msg for sig in sigs : # handles all other messages and None (standalone) pending . append ( ( sig , msg ) ) elif signed . type == MSG_SIGNED : # should be a SignedMsg sigs , msg = signed . sigs , signed . msg for sig in sigs : pending . append ( ( sig , msg ) ) else : raise NotImplementedError ( "Unable to verify %s." % signed ) assigned = ex_verified = im_verified = 0 # Explicit/implicit verification.. # ..is needed so that all assigned signatures are accounted for by explicit # verification and that implicit verification does not excuse failures for # assigned signatures. It's not used for much now, could use for nice logs. # verify all pending for sig , target in pending : keypkt = None signer_id = sig . body . keyid if signer_fprint : # forced a signer to verify against keypkt = key . get_keypkt ( signer_fprint ) signer_id = signer_fprint # this is ugly: it's used to match up the # packet and ID in the 'if keypt:' verify_block() part below elif signer_id in key . list_keyids ( ) : # discover an sig-asserted signer keypkt = key . get_keypkt ( signer_id ) if keypkt : # either the sigpkt specified a key or an fprint was forced assigned += 1 if sig . body . alg_hash not in ( HASH_MD5 , HASH_SHA1 , HASH_SHA224 , HASH_SHA256 , HASH_SHA384 , HASH_SHA512 ) : saplog . warn ( "A signature from ID:%r has an unsupported hash algorithm:%s(%s)." % ( signer_id , sig . body . alg_hash , TXT . alg_hash_msg ( sig . body . alg_hash ) ) ) elif CRYPT . verify ( sig , target , keypkt , * * opts ) : saplog . info ( "Verified a signature from ID:%r." % signer_id ) ex_verified += 1 if _cmp_expiration ( sig , SIGSUB_EXPIRES ) : # if sig expired.. saplog . info ( "..but the signature has expired." ) #..abort elif verify_block ( key , 'key' , signer_id , revocs = revocs ) : success = True else : # room for timestamp/reason for revocation exceptions pass else : saplog . warn ( "A signature from ID:%r failed." % signer_id ) elif not signer_id : # try to verify unassigned sig !! not just else: !! matches = find_keys ( [ key ] , action = 'sign' ) if matches : saplog . warn ( "Attempting to verify an unassigned signature." ) for keyid in matches [ 0 ] [ 1 ] : keypkt = key . get_keypkt ( keyid ) v = False try : v = CRYPT . verify ( sig , target , keypkt , * * opts ) except PGPCryptoError : pass # this doesn't have to verify if v : im_verified += 1 if verify_block ( key , 'key' , keyid , revocs = revocs ) : success = True #if 0 == assigned: #    saplog.warn("No matching key ID was found in key %r." % key.primary_id) if revocs and 'revocs' in kw : kw [ 'revocs' ] . extend ( revocs ) if True == success : # if everything assigned was verified OR it verified as unassigned if ( assigned and assigned == ex_verified ) or im_verified : return msg