> On Nov 4, 2019, at 3:15 AM, Philipp Kunz <philipp.k...@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>

Reply via email to