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