> On Nov 13, 2019, at 8:12 AM, Philipp Kunz <philipp.k...@paratix.ch> wrote:
> 
> Hi Max,
> 
> Thank you for your reply. Your last comment
> 
>> That's not the original attempt, IMO.
> 
> points out well how far I have got only and no further so far.
> 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.
> 2) Jarsigner specs might create the impression that jarsigner can check if a 
> jar file is signed by some entity specified with an alias.
> 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.

The argument has always been named "alias", and an alias means the end-entity 
signer.

It might be useful to check what the CA of the signer is, but in a real 
production environment, first, I don't think people cares about the 
intermediate CAs, second, the root CA is almost always in the cacerts file and 
no one cares about the alias name in that keystore. A rational way we can do is 
to verify with "-verbose -certs" and read the cert chain with subject names. If 
not enough, call "keytool -printcert -jarfile filename" to read more details.

> This is where my last suggestion fits in:
> 
>>> 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)
> 
> 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.
> 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.
> 
> About incompleteness:
> - 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

Adding "-verbose -certs" will show you which alias signs each entry. If the 
result is too long, try "-verbose:grouped -certs".

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

The command above still works. You might find it a little cumbersome because 
all info are stacked with much indentation.

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

I think this is a bug.

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

I still think we should only count the end-entity certs.

Currently, the -verbose -certs output prints out the alias name in parenthesis. 
For example, if my cacert has "ca", and ca signs ca1 sign ca2 signs a (last one 
in this keystore), the output will be something like

      >>> Signer
      X.509, CN=a (a)
      [certificate is valid from 11/13/19, 7:47 PM to 8/9/22, 7:47 PM]
      X.509, CN=ca2
      [certificate is valid from 11/13/19, 7:47 PM to 8/9/22, 7:47 PM]
      X.509, CN=ca1
      [certificate is valid from 11/13/19, 7:47 PM to 8/9/22, 7:47 PM]
      X.509, CN=ca
      [trusted certificate]

Thanks,
Max

> 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.
> 
> Regards,
> Philipp
> 
> 
> 
> On Tue, 2019-11-05 at 15:36 +0800, Weijun Wang wrote:
>>> 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