<html dir="ltr"><head></head><body style="text-align:left; direction:ltr;"><div>Hi Max,</div><div><br></div><div>Thank you for your reply. Your last comment</div><div><br></div><div><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre>That's not the original attempt, IMO.</pre></blockquote></div><div><br></div><div>points out well how far I have got only and no further so far.</div><div>1) jarsigner actually check can verify whether or not a signature including its certificate path can be validated towards some entity specified with an alias.</div><div>2) Jarsigner specs might create the impression that jarsigner can check if a jar file is signed by some entity specified with an alias.</div><div>Both above points are useful in my opinion but both are not the same. Which one to go for is not necessarily a either-or decision. Both could make sense independently.</div><div>This is where my last suggestion fits in:</div><div><br></div><div><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre>Another attempt to solve the confusion could be to change the following sentence, which would not require to change any code at all:</pre><pre>-This JAR contains signed entries which aren't signed by the specified alias(es)</pre><pre>+This JAR contains signed entries the certificate path of which aren't signed by the specified alias(es)</pre></blockquote></blockquote><br></div><div>This would address point 2). I don't think it would hurt to make explicit what the tool actually does unless it is a bug.</div><div>I still miss somehow the big picture and therefore I'm reluctant to propose how to make jarsigner fit it better. From the narrow scope I guess I understand I'm pretty confident that the current situation has some potential for confusion and, hence, for improvement, which I also understand you seem to confirm to some extent.</div><div><br></div><div>About incompleteness:</div><div>- There might be several aliases given in a command that invokes jarsigner -verify and I wouldn't know whether each jar file entry would have to be signed by any or all of the referenced entities</div><div>- There might be several signatures in a jar file and I would not know whether each or any signature of each jar file entry would have to be signed by any or all of the referenced entities</div><div>- Similar as for notSignedByAlias applies most probably also to aliasNotInStore. From just looking at the code, I'm pretty sure that that particular exit code and warning message don't occur if any of the certificates in the signature's chain is in the keystore with a specified alias when they probably should occur if the key pair or certificate for the entity that actually signed the jar file (the end-entity certificate) is not in the keystore with the specified alias(es) (and non-end-entity certificates in the certificate chain in the signature in the jar file should supposedly be disregarded as with notSignedByAlias).</div><div>In summary there are some questions in which cases to consider only end-entity certificates and in which cases the whole chains and other questions as how to logically join expressions for single signatures or aliases into one end result (with and or with or).</div><div>Incomplete is also my knowledge of which of the described scenarios, uses cases, situations or combinations thereof actually are useful or not or in actual use, buggy or correct.</div><div><br></div><div>Regards,</div><div>Philipp</div><div><br></div><div><br></div><div><br></div><div>On Tue, 2019-11-05 at 15:36 +0800, Weijun Wang wrote:</div><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre>On Nov 4, 2019, at 3:15 AM, Philipp Kunz <</pre><a href="mailto:philipp.kunz@paratix.ch"><pre>philipp.kunz@paratix.ch</pre></a><pre>> wrote:</pre><pre><br></pre><pre>Hi,</pre><pre><br></pre><pre>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.</pre></blockquote><pre><br></pre><pre>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.</pre><pre><br></pre><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre><br></pre><pre>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.</pre><pre><br></pre><pre>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.</pre><pre>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.</pre><pre>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.</pre><pre><br></pre><pre>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.</pre><pre><br></pre><pre><br></pre><pre>The specification contains statements related to jarsigner,</pre><a href="https://docs.oracle.com/en/java/javase/13/docs/specs/man/jarsigner.html"><pre>https://docs.oracle.com/en/java/javase/13/docs/specs/man/jarsigner.html</pre></a><pre><br></pre><pre>:</pre><pre><br></pre><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre>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). ...</pre><pre>* Its authenticity can be verified by a computation that uses the public key corresponding to the private key used to generate the signature.</pre></blockquote><pre><br></pre><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre>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).</pre></blockquote><pre><br></pre><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre>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.</pre></blockquote><pre><br></pre><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre>... 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 ...</pre></blockquote><pre><br></pre><pre>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.</pre></blockquote><pre><br></pre><pre>jarsigner -verify should do 2 things:</pre><pre><br></pre><pre>1. Use the JarFile API to validate the signatures.</pre><pre><br></pre><pre>2. Use CertPath API to validate the certificate chain.</pre><pre><br></pre><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre><br></pre><pre><br></pre><pre>The specification contains statements related to keytool,</pre><a href="https://docs.oracle.com/en/java/javase/13/docs/specs/man/keytool.html"><pre>https://docs.oracle.com/en/java/javase/13/docs/specs/man/keytool.html</pre></a><pre><br></pre><pre>:</pre><pre><br></pre><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre>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.</pre></blockquote><pre><br></pre><pre>This above, hence, is how to get the public key certificate that directly corresponds to a private key.</pre><pre><br></pre><pre><br></pre><pre>I haven't found such a bug already existing. The closest I found are:</pre><pre>- </pre><a href="https://bugs.openjdk.java.net/browse/JDK-7004168"><pre>https://bugs.openjdk.java.net/browse/JDK-7004168</pre></a><pre><br></pre><pre>- </pre><a href="https://bugs.openjdk.java.net/browse/JDK-4306329"><pre>https://bugs.openjdk.java.net/browse/JDK-4306329</pre></a><pre><br></pre></blockquote><pre><br></pre><pre>The 1st one is quite similar.</pre><pre><br></pre><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre><br></pre><pre>Attached is a patch for jarsigner that shows an approach to fix it.</pre></blockquote><pre><br></pre><pre>I'll take a look.</pre><pre><br></pre><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre>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.</pre></blockquote><pre><br></pre><pre>Can you please explain more? When more than one aliases are specified, it means I'm OK with either of them being the signer.</pre><pre><br></pre><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre>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.</pre><pre><br></pre><pre><br></pre><pre>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").</pre><pre><br></pre><pre>Another attempt to solve the confusion could be to change the following sentence, which would not require to change any code at all:</pre><pre>-This JAR contains signed entries which aren't signed by the specified alias(es)</pre><pre>+This JAR contains signed entries the certificate path of which aren't signed by the specified alias(es)</pre></blockquote><pre><br></pre><pre>That's not the original attempt, IMO.</pre><pre><br></pre><pre>Thanks,</pre><pre>Max</pre><pre><br></pre><pre><br></pre><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre><br></pre><pre>Opinions?</pre><pre><br></pre><pre>Regards,</pre><pre>Philipp</pre><pre><VerifySignedBySpecifiedAliasWithoutOtherAliasesInCertChain.patch></pre></blockquote><pre><br></pre></blockquote></body></html>