Skip to content

Commit

Permalink
Key alias is not asked by verify().
Browse files Browse the repository at this point in the history
Instead, META-INF/*.SF file is searched. Only exactly one such is allowed.
Its basename tells the key alias.

Closes #9.
  • Loading branch information
KonstantinShemyak committed Apr 1, 2017
1 parent 1590dd8 commit 7db7c2e
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 24 deletions.
23 changes: 16 additions & 7 deletions javatools/jarutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
:license: LGPL
"""

import os
import sys
from zipfile import ZipFile, ZIP_DEFLATED
from tempfile import NamedTemporaryFile
Expand Down Expand Up @@ -57,7 +56,7 @@ class MissingManifestError(Exception):
pass


def verify(certificate, jar_file, key_alias):
def verify(certificate, jar_file):
"""
Verifies signature of a JAR file.
Expand All @@ -74,9 +73,19 @@ def verify(certificate, jar_file, key_alias):
"""

from .crypto import verify_signature_block, SignatureBlockVerificationError
from .manifest import file_matches_sigfile

# Step 0: get the "key alias", used also for naming of sig-related files.
zip_file = ZipFile(jar_file)
sf_data = zip_file.read("META-INF/%s.SF" % key_alias)
sf_files = filter(file_matches_sigfile, zip_file.namelist())
if len(sf_files) == 0:
raise JarSignatureMissingError, "No .SF file in %s" % jar_file
elif len(sf_files) > 1:
raise VerificationError, "Multiple .SF files in %s" % jar_file

sf_filename = sf_files[0]
key_alias = sf_filename[9:-3] # "META-INF/%s.SF"
sf_data = zip_file.read(sf_filename)

# Step 1: check the crypto part.
with NamedTemporaryFile('w') as tmp_buf:
Expand Down Expand Up @@ -231,14 +240,14 @@ def cli_verify_jar_signature(argument_list):
TODO: use trusted keystore;
"""

usage_message = "Usage: jarutil v file.jar trusted_certificate.pem key_alias"
if len(argument_list) != 3:
usage_message = "Usage: jarutil v file.jar trusted_certificate.pem"
if len(argument_list) != 2:
print usage_message
return 1

(jar_file, certificate, key_alias) = argument_list
(jar_file, certificate) = argument_list
try:
verify(certificate, jar_file, key_alias)
verify(certificate, jar_file)
except VerificationError, error_message:
print error_message
return 1
Expand Down
File renamed without changes.
Binary file added tests/data/sig-related-junk-files-ok.jar
Binary file not shown.
39 changes: 22 additions & 17 deletions tests/jarutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,50 +32,55 @@

class JarutilTest(TestCase):

def cli_verify_wrap(self, jar, cert, alias):
data = [get_data_fn(jar), get_data_fn(cert), alias]
def cli_verify_wrap(self, jar, cert):
data = [get_data_fn(jar), get_data_fn(cert)]
result = cli_verify_jar_signature(data)

self.assertEqual(0, result,
"cli_verify_jar_signature() failed on %s with"
" certificate %s, alias %s" % (jar, cert, alias))
" certificate %s" % (jar, cert))

def verify_wrap(self, cert, jar, key, error_prefix):
def verify_wrap(self, cert, jar, error_prefix):
try:
verify(cert, jar, key)
verify(cert, jar)
except VerificationError, error_message:
self.fail("%s: %s" % (error_prefix, error_message))

def test_cli_verify_signature_by_javatools(self):
self.cli_verify_wrap("jarutil-signed.jar", "javatools-cert.pem",
"UNUSED")
self.cli_verify_wrap("jarutil-signed.jar", "javatools-cert.pem")

def test_cli_verify_signature_by_jarsigner(self):
self.cli_verify_wrap("jarutil-signed-by-jarsigner.jar",
"javatools-cert.pem", "UNUSED")
"javatools-cert.pem")

# Tests that signature-related files are skipped when the signature is
# verified. The JAR file is a normal signed JAR, plus junk files with
# "signature-related" names.
# The test does not guarantee that no other files are skipped.
def test_signature_related_files_skip(self):
self.cli_verify_wrap("sig-related-junk-files.jar",
"javatools-cert.pem", "UNUSED")
self.cli_verify_wrap("sig-related-junk-files-ok.jar",
"javatools-cert.pem")

def test_multiple_sf_files(self):
jar_data = get_data_fn("multiple-sf-files.jar")
cert = get_data_fn("javatools-cert.pem")
with self.assertRaises(VerificationError):
verify(cert, jar_data)

def test_ecdsa_pkcs8_verify(self):
self.cli_verify_wrap("ec.jar", "ec-cert.pem", "TEST")
self.cli_verify_wrap("ec.jar", "ec-cert.pem")

def test_missing_signature_block(self):
jar_data = get_data_fn("ec-must-fail.jar")
cert = get_data_fn("ec-cert.pem")
with self.assertRaises(JarSignatureMissingError):
verify(cert, jar_data, "TEST")
verify(cert, jar_data)

def test_tampered_signature_block(self):
jar_data = get_data_fn("ec-tampered.jar")
cert = get_data_fn("ec-cert.pem")
with self.assertRaises(SignatureBlockFileVerificationError):
verify(cert, jar_data, "TEST")
verify(cert, jar_data)


def test_cli_sign_and_verify(self):
Expand All @@ -86,7 +91,7 @@ def test_cli_sign_and_verify(self):
with NamedTemporaryFile() as tmp_jar:
copyfile(src, tmp_jar.name)
cli_sign_jar([tmp_jar.name, cert, key, key_alias])
self.verify_wrap(cert, tmp_jar.name, key_alias,
self.verify_wrap(cert, tmp_jar.name,
"Verification of JAR which we just signed failed")


Expand All @@ -100,7 +105,7 @@ def test_cli_sign_new_file_and_verify(self):
copyfile(src, tmp_jar.name)
cli_sign_jar([tmp_jar.name, cert, key, key_alias,
"-o", dst.name])
self.verify_wrap(cert, dst.name, key_alias,
self.verify_wrap(cert, dst.name,
"Verification of JAR which we just signed failed")


Expand All @@ -112,7 +117,7 @@ def test_cli_sign_and_verify_ecdsa_pkcs8_sha512(self):
with NamedTemporaryFile() as tmp_jar:
copyfile(src, tmp_jar.name)
cli_sign_jar([tmp_jar.name, cert, key, key_alias])
self.verify_wrap(cert, tmp_jar.name, key_alias,
self.verify_wrap(cert, tmp_jar.name,
"Verification of JAR which we just signed failed")


Expand All @@ -129,7 +134,7 @@ def test_sign_with_certchain_and_verify(self):
["-c", root_cert, "-c", intermediate_cert,
tmp_jar.name, signing_cert, key, key_alias]),
"Signing with embedding a chain of certificates failed")
self.verify_wrap(root_cert, tmp_jar.name, key_alias,
self.verify_wrap(root_cert, tmp_jar.name,
"Verification of JAR which we signed embedding chain of certificates failed")


Expand Down

0 comments on commit 7db7c2e

Please sign in to comment.