def sign(jar_file, cert_file, key_file, key_alias, extra_certs=None, digest=None):
    """
    Signs the jar (almost) identically to jarsigner.
    """

    from .crypto import private_key_type

    jar = ZipFile(jar_file, "a")
    if "META-INF/MANIFEST.MF" not in jar.namelist():
        print "META-INF/MANIFEST.MF not found in %s" % jar_file
        return 1

    mf = Manifest()
    mf.parse(jar.read("META-INF/MANIFEST.MF"))

    # create a signature manifest, and make it match the line separator
    # style of the manifest it'll be digesting.
    sf = SignatureManifest(linesep=mf.linesep)

    sf_digest_algorithm = "SHA-256"
    sf.digest_manifest(mf, sf_digest_algorithm)
    jar.writestr("META-INF/%s.SF" % key_alias, sf.get_data())

    sig_digest_algorithm = sf_digest_algorithm  # No point to make it different
    sig_block_extension = private_key_type(key_file)

    jar.writestr("META-INF/%s.%s" % (key_alias, sig_block_extension),
        sf.get_signature(cert_file, key_file, extra_certs, sig_digest_algorithm))

    return 0
 def test_verify_mf_checksums_no_whole_digest(self):
     sf_file = "sf-no-whole-digest.sf"
     mf_file = "sf-no-whole-digest.mf"
     sf = SignatureManifest()
     sf.parse_file(get_data_fn(sf_file))
     mf = Manifest()
     mf.parse_file(get_data_fn(mf_file))
     error_message = sf.verify_manifest_checksums(mf)
     self.assertIsNone(error_message,
         "Verification of signature file %s against manifest %s failed: %s"
         % (sf_file, mf_file, error_message))
Exemple #3
0
 def test_verify_mf_checksums_no_whole_digest(self):
     sf_file = "sf-no-whole-digest.sf"
     mf_file = "sf-no-whole-digest.mf"
     sf = SignatureManifest()
     sf.parse_file(get_data_fn(sf_file))
     mf = Manifest()
     mf.parse_file(get_data_fn(mf_file))
     error_message = sf.verify_manifest_checksums(mf)
     self.assertIsNone(
         error_message,
         "Verification of signature file %s against manifest %s failed: %s"
         % (sf_file, mf_file, error_message))
Exemple #4
0
    def test_multi_digests(self):
        jar_file = "multi-digests.jar"

        mf_ok_file = "one-valid-digest-of-several.mf"
        mf = Manifest()
        mf.parse_file(get_data_fn(mf_ok_file))
        error_message = mf.verify_jar_checksums(get_data_fn(jar_file))
        self.assertIsNone(error_message,
            "Digest verification of %s against JAR %s failed: %s" \
            % (mf_ok_file, jar_file, error_message))

        sf_ok_file = "one-valid-digest-of-several.sf"
        sf = SignatureManifest()
        sf.parse_file(get_data_fn(sf_ok_file))
        error_message = sf.verify_manifest_checksums(mf)
        self.assertIsNone(error_message,
            "Signature file digest verification of %s against manifest %s failed: %s" \
            % (sf_ok_file, mf_ok_file, error_message))
    def test_multi_digests(self):
        jar_file = "multi-digests.jar"

        mf_ok_file = "one-valid-digest-of-several.mf"
        mf = Manifest()
        mf.parse_file(get_data_fn(mf_ok_file))
        error_message = mf.verify_jar_checksums(get_data_fn(jar_file))
        self.assertIsNone(error_message,
            "Digest verification of %s against JAR %s failed: %s" \
            % (mf_ok_file, jar_file, error_message))

        sf_ok_file = "one-valid-digest-of-several.sf"
        sf = SignatureManifest()
        sf.parse_file(get_data_fn(sf_ok_file))
        error_message = sf.verify_manifest_checksums(mf)
        self.assertIsNone(error_message,
            "Signature file digest verification of %s against manifest %s failed: %s" \
            % (sf_ok_file, mf_ok_file, error_message))
Exemple #6
0
    def test_multi_digests(self):
        jar_file = "multi-digests.jar"

        mf_ok_file = "one-valid-digest-of-several.mf"
        mf = Manifest()
        mf.parse_file(get_data_fn(mf_ok_file))
        errors = mf.verify_jar_checksums(get_data_fn(jar_file))
        self.assertEqual(
            0, len(errors), "The following entries in jar file %s do not match"
            " in manifest %s: %s" % (jar_file, mf_ok_file, ",".join(errors)))

        sf_ok_file = "one-valid-digest-of-several.sf"
        sf = SignatureManifest()
        sf.parse_file(get_data_fn(sf_ok_file))

        errors = sf.verify_manifest(mf)
        self.assertEqual(
            0, len(errors),
            "The following entries in signature file %s against manifest %s"
            " failed: %s" % (sf_ok_file, mf_ok_file, ",".join(errors)))
    def test_verify_mf_checksums_no_whole_digest(self):
        sf_file = "test_manifest/sf-no-whole-digest.sf"
        mf_file = "test_manifest/sf-no-whole-digest.mf"
        sf = SignatureManifest()
        sf.parse_file(get_data_fn(sf_file))
        mf = Manifest()
        mf.parse_file(get_data_fn(mf_file))

        self.assertFalse(
            sf.verify_manifest_main_checksum(mf),
            "Verification of main signature in file %s against manifest %s"
            " succeeded, but the SF file has no Digest-Manifest section"
            % (sf_file, mf_file))

        self.assertTrue(
            sf.verify_manifest_main_attributes_checksum(mf),
            "Verification of Main-Attibutes in file %s against manifest %s"
            "failed" % (sf_file, mf_file))

        errors = sf.verify_manifest_entry_checksums(mf)
        self.assertEqual(
            0, len(errors),
            "The following entries in signature file %s against manifest %s"
            " failed: %s"
            % (sf_file, mf_file, ",".join(errors)))
    def test_multi_digests(self):
        jar_file = "test_manifest/multi-digests.jar"

        mf_ok_file = "test_manifest/one-valid-digest-of-several.mf"
        mf = Manifest()
        mf.parse_file(get_data_fn(mf_ok_file))
        errors = mf.verify_jar_checksums(get_data_fn(jar_file))
        self.assertEqual(
            0, len(errors),
            "The following entries in jar file %s do not match"
            " in manifest %s: %s"
            % (jar_file, mf_ok_file, ",".join(errors)))

        sf_ok_file = "test_manifest/one-valid-digest-of-several.sf"
        sf = SignatureManifest()
        sf.parse_file(get_data_fn(sf_ok_file))

        errors = sf.verify_manifest(mf)
        self.assertEqual(
            0, len(errors),
            "The following entries in signature file %s against manifest %s"
            " failed: %s"
            % (sf_ok_file, mf_ok_file, ",".join(errors)))
Exemple #9
0
    def test_verify_mf_checksums_no_whole_digest(self):
        sf_file = "sf-no-whole-digest.sf"
        mf_file = "sf-no-whole-digest.mf"
        sf = SignatureManifest()
        sf.parse_file(get_data_fn(sf_file))
        mf = Manifest()
        mf.parse_file(get_data_fn(mf_file))

        self.assertFalse(
            sf.verify_manifest_main_checksum(mf),
            "Verification of main signature in file %s against manifest %s"
            " succeeded, but the SF file has no Digest-Manifest section" %
            (sf_file, mf_file))

        self.assertTrue(
            sf.verify_manifest_main_attributes_checksum(mf),
            "Verification of Main-Attibutes in file %s against manifest %s"
            "failed" % (sf_file, mf_file))

        errors = sf.verify_manifest_entry_checksums(mf)
        self.assertEqual(
            0, len(errors),
            "The following entries in signature file %s against manifest %s"
            " failed: %s" % (sf_file, mf_file, ",".join(errors)))
Exemple #10
0
def cli_sign_jar(options, jar_file, cert_file, key_file, key_alias):
    """
    Signs the jar (almost) identically to jarsigner.
    """

    from .crypto import private_key_type, CannotFindKeyTypeError

    jar = ZipFile(jar_file, "a")
    if not "META-INF/MANIFEST.MF" in jar.namelist():
        print "META-INF/MANIFEST.MF not found in %s" % jar_file
        return 1

    try:
        sig_block_extension = private_key_type(key_file)
    except CannotFindKeyTypeError:
        print "Cannot determine private key type (is it in PEM format?)"
        return 1

    mf = Manifest()
    mf.parse(jar.read("META-INF/MANIFEST.MF"))

    # create a signature manifest, and make it match the line separator
    # style of the manifest it'll be digesting.
    sf = SignatureManifest(linesep=mf.linesep)

    sf_digest_algorithm = "SHA-256"
    if options and options.digest:
        sf_digest_algorithm = options.digest
    sf.digest_manifest(mf, sf_digest_algorithm)
    jar.writestr("META-INF/%s.SF" % key_alias, sf.get_data())

    sig_digest_algorithm = sf_digest_algorithm  # No point to make it different
    jar.writestr("META-INF/%s.%s" % (key_alias, sig_block_extension),
        sf.get_signature(cert_file, key_file, sig_digest_algorithm))

    return 0
Exemple #11
0
def verify(certificate, jar_file, key_alias):
    """
    Verifies signature of a JAR file.

    Limitations:
    - diagnostic is less verbose than of jarsigner
    :return: tuple (exit_status, result_message)

    Reference:
    http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#Signature_Validation
    Note that the validation is done in three steps. Failure at any step is a
    failure of the whole validation.
    """

    from .crypto import verify_signature_block
    from tempfile import mkstemp

    zip_file = ZipFile(jar_file)
    sf_data = zip_file.read("META-INF/%s.SF" % key_alias)

    # Step 1: check the crypto part.
    sf_file = mkstemp()[1]
    with open(sf_file, "w") as tmp_buf:
        tmp_buf.write(sf_data)
        tmp_buf.flush()
        file_list = zip_file.namelist()
        sig_block_filename = None
        # JAR specification mentions only RSA and DSA; jarsigner also has EC
        signature_extensions = ("RSA", "DSA", "EC")
        for extension in signature_extensions:
            candidate_filename = "META-INF/%s.%s" % (key_alias, extension)
            if candidate_filename in file_list:
                sig_block_filename = candidate_filename
                break
        if sig_block_filename is None:
            return "None of %s found in JAR" % \
                   ", ".join(key_alias + "." + x for x in signature_extensions)

        sig_block_data = zip_file.read(sig_block_filename)
        error = verify_signature_block(certificate, sf_file, sig_block_data)
        os.unlink(sf_file)
        if error is not None:
            return error

    # KEYALIAS.SF is correctly signed.
    # Step 2: Check that it contains correct checksum of the manifest.
    signature_manifest = SignatureManifest()
    signature_manifest.parse(sf_data)

    jar_manifest = Manifest()
    jar_manifest.parse(zip_file.read("META-INF/MANIFEST.MF"))

    error = signature_manifest.verify_manifest_checksums(jar_manifest)
    if error is not None:
        return error

    # Checksums of MANIFEST.MF itself are correct.
    # Step 3: Check that it contains valid checksums for each file from the JAR.
    error = jar_manifest.verify_jar_checksums(jar_file)
    if error is not None:
        return error

    return None