code: def _parse_signature(stream):
      
      p = {'type': 'signature'}
  
      to_hash = io.BytesIO()
      with stream.capture(to_hash):
          p['version'] = stream.readfmt('B')
          p['sig_type'] = stream.readfmt('B')
          p['pubkey_alg'] = stream.readfmt('B')
          p['hash_alg'] = stream.readfmt('B')
          p['hashed_subpackets'] = parse_subpackets(stream)
  
      # https://tools.ietf.org/html/rfc4880#section-5.2.4
      tail_to_hash = b'\x04\xff' + struct.pack('>L', to_hash.tell())
  
      p['_to_hash'] = to_hash.getvalue() + tail_to_hash
  
      p['unhashed_subpackets'] = parse_subpackets(stream)
      embedded = list(_parse_embedded_signatures(p['unhashed_subpackets']))
      if embedded:
          log.debug('embedded sigs: %s', embedded)
          p['embedded'] = embedded
  
      p['hash_prefix'] = stream.readfmt('2s')
      if p['pubkey_alg'] in ECDSA_ALGO_IDS:
          p['sig'] = (parse_mpi(stream), parse_mpi(stream))
      elif p['pubkey_alg'] in RSA_ALGO_IDS:  # RSA
          p['sig'] = (parse_mpi(stream),)
      elif p['pubkey_alg'] == DSA_ALGO_ID:
          p['sig'] = (parse_mpi(stream), parse_mpi(stream))
      else:
          log.error('unsupported public key algo: %d', p['pubkey_alg'])
  
      assert not stream.read()
      return p
docs: See https://tools.ietf.org/html/rfc4880#section-5.2 for details.