jarsigner notSignedByAlias

Philipp Kunz philipp.kunz at paratix.ch
Sun Nov 3 19:15:57 UTC 2019


Hi,

Regarding notSignedByAlias warning and exit code (32), it looks like
these don't occur if the specified alias for verifying a jar points to
a keystore entry that signs (or certifies) one of the certificates in
the jar's signature attached certificate chain. That may be useful to
check if a signature and its certification path can be verified the
usual way but in order to verify exactly who originally signed a jar it
may be confusing, misleading, or maybe possibly even wrong.

I would have guessed from the warning "This JAR contains signed entries
which aren't signed by the specified alias(es)." or more specifically
from its absence that the keystore entry the specified alias points to
actually has signed the verified jar, which I believe to have found is
not currently always the case. The warning and exit code don't occur,
too, if one certificate of the certificate chain included in the jar
signature matches the keystore entry the specified alias points to.

As an example, lets consider an example with a key pair ca that acts as
a certificate authority and another key pair b which has a certificate
of ca, see attached
VerifySignedBySpecifiedAliasWithoutOtherAliasesInCertChain.
When a jar is signed with b, jarsigner -verify will accept the
resulting jar as signed not only by b itself but also by ca, or the
notSignedByAlias warning and exit code should have occurred.
If I imagine the ca in this example to be a real certificate authority
such as Geotrust or Verisign and b a certificate for my own key pair
signed or certified by such a real ca, I could make jarsigner act on a
jar as though it had been signed by these certificate authorities
themselves.

For verifying authenticity of a signed jar meaning that it has been
signed by the entity referred to by the specified alias, I figure that
it is not enough to verify that the key pair used to sign the jar has a
certificate chain that includes a certificate that matches the keystore
entry specified by the given alias. I figure it is also necessary to
only compare the one certificate from the signed jar signature that
directly corresponds to the private key used to sign the jar.


The specification contains statements related to jarsigner,
https://docs.oracle.com/en/java/javase/13/docs/specs/man/jarsigner.html
:

> A digital signature is a string of bits that is computed from some
data (the data being signed) and the private key of an entity (a
person, company, and so on). ...
> * Its authenticity can be verified by a computation that uses the
public key corresponding to the private key used to generate the
signature.

> The jarsigner command uses an entity's private key to generate a
signature. The signed JAR file contains, among other things, a copy of
the certificate from the keystore for the public key corresponding to
the private key used to sign the file. The jarsigner command can verify
the digital signature of the signed JAR file using the certificate
inside it (in its signature block file).

> This file also contains, encoded inside it, the certificate or
certificate chain from the keystore that authenticates the public key
corresponding to the private key used for signing.

> ... and in parentheses, the keystore alias for the signer when the
public key certificate in the JAR file matches the one in a keystore
entry ...

Public and private key pairs are mentioned a number of times,
explaining in general how a private key is involved in signing and its
corresponding public key certificate in verifying the resulting
signature. The exact behavior of "jarsigner -verify" is not explicitly
defined, which in my opinion is fine as it should be deducible from the
quoted statements.


The specification contains statements related to keytool,
https://docs.oracle.com/en/java/javase/13/docs/specs/man/keytool.html
:

> The keytool command can create and manage keystore key entries that
each contain a private key and an associated certificate chain. The
first certificate in the chain contains the public key that corresponds
to the private key.

This above, hence, is how to get the public key certificate that
directly corresponds to a private key.


I haven't found such a bug already existing. The closest I found are:
- https://bugs.openjdk.java.net/browse/JDK-7004168
- https://bugs.openjdk.java.net/browse/JDK-4306329


Attached is a patch for jarsigner that shows an approach to fix it.
However, I think it is still incomplete. In order to be complete, I
think it should also check that "jarsigner -verify" works well if more
than one aliases are specified for the same invocation. And similar for
"not in keystore". Furthermore, I changed existing ConciseJarsigner
test to let it continue passing where I believe an exit code has been
put from previous results incompletely verified, which should be
confirmed.


The current behavior can be used to check if a valid certification path
can be found from the signed content and any of its certificate chain
certificates to a keystore entry referred to by a specified alias which
looks useful. It is only confusing that the specification or
documentation does not state it explicitly. At the moment I would not
know how to invoke "jarsigner -verify" in a way to check if some
content has been signed by a specific entity referred to by a given
alias disregarding the certification path of the signature (as in the
keytool's statement "The first certificate in the chain contains the
public key that corresponds to the private key").

Another attempt to solve the confusion could be to change the following
sentence, which would not require to change any code at all:
-This JAR contains signed entries which aren't signed by the specified
alias(es)
+This JAR contains signed entries the certificate path of which aren't
signed by the specified alias(es)

Opinions?

Regards,
Philipp
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/security-dev/attachments/20191103/9cf1befb/attachment.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: VerifySignedBySpecifiedAliasWithoutOtherAliasesInCertChain.patch
Type: text/x-patch
Size: 6102 bytes
Desc: not available
URL: <https://mail.openjdk.org/pipermail/security-dev/attachments/20191103/9cf1befb/VerifySignedBySpecifiedAliasWithoutOtherAliasesInCertChain.patch>


More information about the security-dev mailing list