def test_commit_signer_has_signed_ca(self):
        """
    Verify that whoever signed the commit has also signed the contributor
    agreement / copyright assignment.
    """
        if sys.version_info < (3, 0, 0):
            self.skipTest("no pgpy on this python version")
        import pgpy  # pylint: disable=import-error

        repodir = get_repo_dir()
        feature_sha1 = os.environ.get("TRAVIS_PULL_REQUEST_SHA")
        signer_encoded = subprocess.check_output(
            ["git", "show", "-s", r'--pretty="%GK"', feature_sha1],
            cwd=repodir).decode("utf-8").strip().strip('"')

        with open(os.path.join(
                repodir, "cmakelang/contrib/signature_db.json")) as infile:
            sigdb = json.load(infile)

        for sigentry in sigdb:
            clearsign = format_signature(sigentry["signature"])
            sig = pgpy.PGPSignature()
            sig.parse(clearsign)
            if sig.signer == signer_encoded:
                return

        self.fail("Could not find signer {} in signature database".format(
            signer_encoded))
Beispiel #2
0
def importSignature(signature: typing.Union[Path, bytes]):
    if isinstance(signature, Path):
        with MMap(signature) as m:
            return importSignature(m)
    else:
        s = pgpy.PGPSignature()
        return s.parse(signature)
def verify(pub_key, message, signature):
    pub_key, _ = pgpy.PGPKey.from_blob(pub_key)
    temp_pgpy = pgpy.PGPSignature()
    temp_pgpy.parse(signature)
    if pub_key.verify(message, temp_pgpy):
        return True
    else:
        return False
Beispiel #4
0
 def get_signature_informations(self):
     """Get message signature features."""
     signed_parts = [
         x for x in self.message.attachments if 'pgp-sign' in x.content_type
     ]
     if not signed_parts:
         return {}
     sign = pgpy.PGPSignature()
     features = {'message_signed': True, 'message_signature_type': 'PGP'}
     try:
         sign.parse(signed_parts[0].data)
         features.update({'message_signer': sign.signer})
     except Exception as exc:
         log.error('Unable to parse pgp signature {}'.format(exc))
     return features
Beispiel #5
0
    def verify_signature(
        self,
        *,
        data: bytes,
        armored_detached_signature: str,
        armored_public_key: str,
    ) -> bool:
        # Load sig
        signature: pgpy.PGPSignature = pgpy.PGPSignature()
        signature.parse(armored_detached_signature)

        # Load key
        key: pgpy.PGPKey = pgpy.PGPKey()
        key.parse(armored_public_key)

        # Verify
        verified: pgpy.types.SignatureVerification = key.verify(
            data, signature)
        is_verified: bool = bool(verified)

        return is_verified
Beispiel #6
0
    def verify(self, authors: Manager) -> VerifiedMessage:
        try:
            author = authors.get(email=self.sender_address)
        except ObjectDoesNotExist:
            raise AuthorUnknown(self.sender_address)
        if not author.pgp_public_key:
            raise AuthorNotVerifyable(author)

        expected_public_key = pgpy.PGPKey()
        expected_public_key.parse(author.pgp_public_key)

        # Mandatory: Verify Signature
        if not self._signature:
            raise NoSignature(self)

        attached_signature = pgpy.PGPSignature()
        attached_signature.parse(self._signature)

        # Verify signature
        if not (attached_signature.signer_fingerprint
                == expected_public_key.fingerprint):
            raise SignatureMismatch(expected_public_key.fingerprint,
                                    attached_signature.signer_fingerprint)

        # Optional: If a public key was attached, verify it for good measure
        if self._public_key:
            attached_pub_key = pgpy.PGPKey()
            attached_pub_key.parse(self._public_key)

            # Verify public Key
            if not expected_public_key.fingerprint == attached_pub_key.fingerprint:
                raise PublicKeyMismatch(expected_public_key, attached_pub_key)

        return VerifiedMessage(subject=self._message.get('subject'),
                               body=self._body,
                               author=author)
    def test_signatures(self):
        """
    Iterate over signatures and verify them.
    """
        gpg_argv = ["gpg", "--homedir", self.homedir]

        if sys.version_info < (3, 0, 0):
            self.skipTest("no pgpy on this python version")

        # TODO(josh): For some reason importing pgpy seems to cause the
        # stderr filedescriptor to leak when we subprocess below. pgpy must be
        # doing some ugly subprocess thing on it's own
        warnings.simplefilter("ignore", ResourceWarning)

        # TODO(josh): pgpy seems to import distutils and the version distributed
        # with virtualenv on this system has an outdated import of `imp` instead
        # of `importlib`.
        with warnings.catch_warnings():
            warnings.simplefilter("ignore", DeprecationWarning)
            import pgpy  # pylint: disable=import-error

        repodir = get_repo_dir()
        with open(os.path.join(
                repodir, "cmakelang/contrib/signature_db.json")) as infile:
            sigdb = json.load(infile)

        # First, get a list of keys already in the local keyring
        known_fingerprints = set()
        proc = subprocess.Popen(gpg_argv + ["--fingerprint", "--with-colons"],
                                stdout=subprocess.PIPE)
        for line in proc.stdout:
            parts = line.decode("utf-8").split(":")
            if parts[0] == "fpr":
                fingerprint = parts[-2]
                known_fingerprints.add(fingerprint[-16:])
        proc.wait()

        # Now do a scan through the database and get a list of any keys we are
        # missing
        needkeys = []
        for sigentry in sigdb:
            clearsign = format_signature(sigentry["signature"])
            sig = pgpy.PGPSignature()
            sig.parse(clearsign)
            if sig.signer not in known_fingerprints:
                needkeys.append(sig.signer)

        if needkeys:
            # TODO(josh): use SKS pool instead of specific server
            result = subprocess.check_call(
                gpg_argv +
                ["--keyserver", "keyserver.ubuntu.com", "--recv-keys"] +
                needkeys)
            self.assertEqual(result,
                             0,
                             msg="Failed to fetch all keys from keyserver")

        with open(os.path.join(
                repodir, "cmakelang/contrib/individual_ca.txt")) as infile:
            template = infile.read()

        # Then verify all the signatures
        for sigentry in sigdb:
            clearsign = format_signature(sigentry["signature"])
            document = construct_agreement_text(template, sigentry)
            with tempfile.NamedTemporaryFile(delete=False) as outfile:
                outfile.write(clearsign.encode("utf-8"))
                detached_sig = outfile.name
            with tempfile.NamedTemporaryFile(delete=False) as outfile:
                outfile.write(document.encode("utf-8"))
                document_msg = outfile.name

            with open(os.devnull, "w") as devnull:
                proc = subprocess.Popen(
                    gpg_argv + ["--verify", detached_sig, document_msg],
                    stderr=devnull)
                result = proc.wait()
            self.assertEqual(0,
                             result,
                             msg="Failed to verify signature for {}\n\n"
                             "See {} and {}".format(sigentry["name"],
                                                    detached_sig,
                                                    document_msg))
            os.unlink(detached_sig)
            os.unlink(document_msg)
    def test_signatures(self):
        """
    Iterate over signatures and verify them.
    """

        if sys.version_info < (3, 0, 0):
            self.skipTest("no pgpy on this python version")
        import pgpy  # pylint: disable=import-error

        repodir = get_repo_dir()
        with open(
                os.path.join(
                    repodir,
                    "cmake_format/contrib/signature_db.json")) as infile:
            sigdb = json.load(infile)

        # First, get a list of keys already in the local keyring
        known_fingerprints = set()
        proc = subprocess.Popen(["gpg", "--fingerprint", "--with-colons"],
                                stdout=subprocess.PIPE)
        for line in proc.stdout:
            parts = line.decode("utf-8").split(":")
            if parts[0] == "fpr":
                fingerprint = parts[-2]
                known_fingerprints.add(fingerprint[-16:])
        proc.wait()

        # Now do a scan through the database and get a list of any keys we are
        # missing
        needkeys = []
        for sigentry in sigdb:
            clearsign = format_signature(sigentry["signature"])
            sig = pgpy.PGPSignature()
            sig.parse(clearsign)
            if sig.signer not in known_fingerprints:
                needkeys.append(sig.signer)

        if needkeys:
            # TODO(josh): use SKS pool instead of specific server
            result = subprocess.check_call(
                ["gpg", "--keyserver", "keyserver.ubuntu.com", "--recv-keys"] +
                needkeys)
            self.assertEqual(result,
                             0,
                             msg="Failed to fetch all keys from keyserver")

        with open(
                os.path.join(
                    repodir,
                    "cmake_format/contrib/individual_ca.txt")) as infile:
            template = infile.read()

        # Then verify all the signatures
        for sigentry in sigdb:
            clearsign = format_signature(sigentry["signature"])
            document = construct_agreement_text(template, sigentry)
            with tempfile.NamedTemporaryFile(delete=False) as outfile:
                outfile.write(clearsign.encode("utf-8"))
                detached_sig = outfile.name
            with tempfile.NamedTemporaryFile(delete=False) as outfile:
                outfile.write(document.encode("utf-8"))
                document_msg = outfile.name

            with open(os.devnull, "w") as devnull:
                proc = subprocess.Popen(
                    ["gpg", "--verify", detached_sig, document_msg],
                    stderr=devnull)
                result = proc.wait()
            self.assertEqual(0,
                             result,
                             msg="Failed to verify signature for {}\n\n"
                             "See {} and {}".format(sigentry["name"],
                                                    detached_sig,
                                                    document_msg))
            os.unlink(detached_sig)
            os.unlink(document_msg)