jarsigner notSignedByAlias

Weijun Wang weijun.wang at oracle.com
Tue Nov 5 07:36:29 UTC 2019


> On Nov 4, 2019, at 3:15 AM, Philipp Kunz <philipp.kunz at paratix.ch> wrote:
> 
> 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.

You are right. That warning should only be shown when the end-entity certificate is not from one of the specified aliases. As for the CA certs (intermediate or root), the authentication should be checked by CertPath validation.

> 
> 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.

jarsigner -verify should do 2 things:

1. Use the JarFile API to validate the signatures.

2. Use CertPath API to validate the certificate chain.

> 
> 
> 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

The 1st one is quite similar.

> 
> Attached is a patch for jarsigner that shows an approach to fix it.

I'll take a look.

> 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.

Can you please explain more? When more than one aliases are specified, it means I'm OK with either of them being the signer.

> 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)

That's not the original attempt, IMO.

Thanks,
Max


> 
> Opinions?
> 
> Regards,
> Philipp
> <VerifySignedBySpecifiedAliasWithoutOtherAliasesInCertChain.patch>




More information about the security-dev mailing list