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