Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 317764

Summary: Could there be a "prefer signed" option?
Product: [Eclipse Project] Equinox Reporter: David Williams <david_williams>
Component: p2Assignee: P2 Inbox <equinox.p2-inbox>
Status: CLOSED WONTFIX QA Contact:
Severity: enhancement    
Priority: P3 CC: aniefer, john.arthorne, matthew, pascal, thomas, tjwatson
Version: 3.6   
Target Milestone: ---   
Hardware: PC   
OS: Windows 7   
Whiteboard: stalebug
Attachments:
Description Flags
screenshot of the pb none

Description David Williams CLA 2010-06-23 22:26:26 EDT
I've seen this issue come up a few times, so wanted to capture the use case, here ... not sure if it is a common case, or feasible to implement. 

Some bundles are not signed every build. (for example, WTP doesn't sign every build ... just because it is so expensive to do so ... especially if you do "continuous builds"). 

So, if someone installs or "mirrors" one of those, then it will never be replaced, unless the qualifier changes ... even once it is signed 
in a later build. 

Seems it would be nice to have some metadata to say if the IU had been signed and for mirror tasks and install tasks to allow a "prefer signed" option so an IU with same qualifier would be replaced, if a signed version was available. 

I guess it is debatable, but to me, a signed bundle and an unsigned bundle do have the "same bits" (same executable code) ... just difference is signing. 
It seems unreasonable to me to have to have a new qualifier, just to say you now have a signed version. And, seems kind of inefficient to say you just have to sign each and every build ... and, even if that was the policy, seems like mistakes could happen, and could not be "recovered from" unless everything given a new qualifier. 

So ... if no one else ever has this problem ... then maybe we'll just start signing each and every build :( 

If there was such a "prefer signed" option, then I'd think "true" should be the default (as it'd be rare not to want that?) ... but, guess it could be argued to maintain backward compatibility to leave "false" as the default.
Comment 1 John Arthorne CLA 2010-06-24 16:55:47 EDT
(In reply to comment #0)
> I guess it is debatable, but to me, a signed bundle and an unsigned bundle do
> have the "same bits" (same executable code) ... just difference is signing. 
> It seems unreasonable to me to have to have a new qualifier, just to say you
> now have a signed version.

Signed versus unsigned bundles do not have the same bits and that fact isn't debatable ;) Executable code is only one possible part of the "bits" that make up a bundle, and since at least the MANIFEST.MF is changed then the contents of the bundle jar are different.

So, while it wouldn't be impossible to introduce such an option, it would mean changing the identity of an installable unit to be more than an [id,version] pair, to something like [id,version,signedness]. The notion of an [id,version] pair uniquely identifying an installable unit is a pretty deeply ingrained concept in p2.
Comment 2 Thomas Hallgren CLA 2010-06-24 17:26:41 EDT
On the other hand, you could look at signing as part of the delivery mechanism, just as we do with pack.gz. You compile and jar things together. That creates the bits. The way we deliver those bits doesn't affect the id and version. We optionally sign sign and pack them. When installing, we optoinally both unpack and unjar. So we might have at least four forms of the same bits.

The folder
The signed jar
The unsigned jar
The jar.pack.gz

All of them are represented by the same id and version and we already do prefer one delivery mechanism over another (.jar.pack.gz over .jar). So why not prefer signed over unsigned?
Comment 3 David Williams CLA 2010-06-25 09:48:35 EDT
> Signed versus unsigned bundles do not have the same bits and that fact isn't
> debatable ;) Executable code is only one possible part of the "bits" ...

Hmm, I wonder why the qualifier doesn't change, then? :) Plus, I think everyone would agree that conditioning a jar in preparation to be packed (and signed) really can change the bits, so there is another case the qualifier should be incremented? 

Or, I guess it could be said we have quantum bundles ... that they don't really exist until observed. And unconditioned, unsigned bundles are never observed. [can you tell, I've been watching the science channel a lot lately] :) 

Of course, we all know in reality, not every bundle is always conditioned and signed in every build. Maybe it should be, but ... hard to do, hard to insist on .... another case where p2 expects a level of perfection that's hard to achieve. 

I like the "distribution" idea Thomas mentioned. In fact, one could imagine a solution where mirror and install tasks had options that said "fail if bundles are not signed" or "fail if bundles are not conditioned" ... you would need a list of exceptions, since not literally every bundle is intended to be signed or conditioned. That "fail rule" would certainly prevent "bad repos" from being created ... I wonder how long it would take to create one of those? Seems easier just to say "prefered signed" and let the repo be a little bit imperfect at times -- that is, allow incremental improvement.  

But ... I agree, there is no obvious and easy (perfect?) solution.
Comment 4 John Arthorne CLA 2010-06-25 10:07:49 EDT
(In reply to comment #2)
> On the other hand, you could look at signing as part of the delivery mechanism,
> just as we do with pack.gz. You compile and jar things together. That creates
> the bits. The way we deliver those bits doesn't affect the id and version. We
> optionally sign sign and pack them. When installing, we optionally both unpack
> and unjar. So we might have at least four forms of the same bits.
> 
> The folder
> The signed jar
> The unsigned jar
> The jar.pack.gz
> 
> All of them are represented by the same id and version and we already do prefer
> one delivery mechanism over another (.jar.pack.gz over .jar). So why not prefer
> signed over unsigned?

There is an important difference here. There is one unique artifact key (id/version) representing the artifact. There can be multiple representations of that artifact in a repository (jar, pack.gz, etc). Each of those representations includes a description of the transformations that need to happen as it is transferred, so that in all cases you end up with the identical result. That is the key point - it allows different representations in the repository for storage and transport efficiency reasons, but in all cases the end result must be identical. The difference with signed vs. unsigned is that you would not end up with the same result so the different representations are not equivalent.
Comment 5 John Arthorne CLA 2010-06-25 10:12:12 EDT
(In reply to comment #3)
> > Signed versus unsigned bundles do not have the same bits and that fact isn't
> > debatable ;) Executable code is only one possible part of the "bits" ...
> 
> Hmm, I wonder why the qualifier doesn't change, then? :) Plus, I think everyone
> would agree that conditioning a jar in preparation to be packed (and signed)
> really can change the bits, so there is another case the qualifier should be
> incremented? 
> 
> Or, I guess it could be said we have quantum bundles ... that they don't really
> exist until observed. And unconditioned, unsigned bundles are never observed.
> [can you tell, I've been watching the science channel a lot lately] :) 

They don't really exist until they are "published" into some repository. Of course the bundle undergoes transformation while it is being built, but once it is built and made available to the world, it needs to stay unchanged. Otherwise as you noted originally, if someone has installed it already they have no way to get a different copy of the same id/version again.
Comment 6 Thomas Hallgren CLA 2010-06-25 10:25:51 EDT
Your assumption would hold true if the .jar file was normalized in all cases but I think Davids point concerns what should happen if signing occurs in a new delivery once a deliver with unsigned material has been made. Compare that with what happens if a delivery is first made without normalizing and packing and then it's followed by a delivery where packing was made. The pack200 is far more intrusive in that it actually does change the bits in the included .class files. I.e. you have a scenario that with great certainty will yield different representations depending on preferred transportation.

You name storage and efficiency as things being separate from the actual identified artifact. But what about integrity? It's still just a transportation concern. What harm could come from favoring that that cannot come from favoring pack200?
Comment 7 John Arthorne CLA 2010-06-25 10:40:35 EDT
(In reply to comment #6)
> Your assumption would hold true if the .jar file was normalized in all cases
> but I think Davids point concerns what should happen if signing occurs in a new
> delivery once a deliver with unsigned material has been made. Compare that with
> what happens if a delivery is first made without normalizing and packing and
> then it's followed by a delivery where packing was made. The pack200 is far
> more intrusive in that it actually does change the bits in the included .class
> files. I.e. you have a scenario that with great certainty will yield different
> representations depending on preferred transportation.

If you had two representations for the same artifact, one being a non-normalized jar and the other being pack200.gz, it would be a bug from the p2 design perspective. Different users installing the same artifact key could end up with a different result in their install. This is a bad outcome - installs aren't reproducible and support/serviceability becomes a problem. Imagine asking a user, "you say you have Feature X, version Y installed, but *which* Feature X, version Y do you have?

> You name storage and efficiency as things being separate from the actual
> identified artifact. But what about integrity? It's still just a 
> transportation concern. What harm could come from favoring that that 
> cannot come from favoring pack200?

There is no problem with favouring one artifact representation over another as long as the result is the same. Signed jars are not the same as unsigned jars. This isn't only a transportation concern because signed jars can behave quite differently from unsigned jars if you have runtime signature verification enabled.
Comment 8 Andrew Niefer CLA 2010-06-25 11:36:36 EDT
We have mirroring tools for comparing against previous builds.  When using a
baseline, if a bundle has the same version from the previous build then the
artifact is taken from the previous build.

(We can also do a "smart" comparison, to help decide if the jar needs to be
retagged with a higher version.  Signing and conditioning should both show up
as differences.  Signing because of the signature files added, and conditioning
because of changes around the eclipse.inf file).

However, I doubt that anyone is using this other than the platform.  If
everyone always did this comparison against previous builds then it would be a
little more explicit that they need to up-version for any changes.
Comment 9 Thomas Hallgren CLA 2010-06-26 00:31:18 EDT
(In reply to comment #7)
> There is no problem with favouring one artifact representation over another as
> long as the result is the same. Signed jars are not the same as unsigned jars.

Were is the recommendation that says - if you want to sign a bundle, you better change it's version?

> This isn't only a transportation concern because signed jars can behave quite
> differently from unsigned jars if you have runtime signature verification
> enabled.

That can be said about a unpacked versus packed jars too when you have pack200 enabled. Sure, you can put an unpacked jar in the repository as a sibling to cover that, but it doesn't change anything. You would get a more or less identical situation using different artifact descriptors for signed and unsigned.

Two use-cases:
1. I use a bundle in my product. The original is found in a Maven repository which makes it cumbersome to deal with from an install perspective. I therefore decide to put it in the repository that I'm publishing. As part of that, I decide to pack the jar, relying on that the pack200 utility will not break my installs. I do thorough tests to verify that everything works as expected.

2. An organization prefer that the employees use an internal repository of blessed things. This repository will only contain signed material. A central function downloads required material from the net, verifies that it is OK, signs it, and adds it to the blessed repository. The whole idea with the repository is to increase quality and security so the repository is rigorously tested.

Both use-cases show a scenario where the bits do change. The relevance is that p2 is used merely as a provisioning mechanism and the user makes the most out of it. It's never involved in the build of the artifacts so tweaking versions is not possible (that would indeed break things). I'm not sure I see any problems with that.
Comment 10 David Williams CLA 2012-05-24 14:25:43 EDT
This issue has come back into my consciousness due to the Foundation's "old" certificate expiring in April, 2012, so many bundles built before then show a warning of expired certificate, and while no known cases of that hurting anything, to get the new signature requires rebuilding, with new qualifier, not merely "resigning" the jar. 

I am not sure p2 could ever efficiently pick a new jar, if it had "a more recent signature" ... guess it could if part of metadata ... but would be kind of cool to merely resign, and not have to change qualifier, for every bundle, every few years, just to get new signing certificate. 

(And, yes, yes, I know, different bits ... but ... not associated with executable function :).

Just thinking out-loud, I suppose an alternative approach would be a tool, say a "jarsignerupdater" which would resign the jar and add a letter, say, to the qualifier. This would have "trickle" effect that features, etc, should have to be changed, but ... its a good thought experiment, since it shows "nothings really changed" about the bundle, except the qualifier (well, and signature :)
Comment 11 Pascal Rapicault CLA 2012-05-24 20:12:33 EDT
I've always been surprised by the expiration of the certificates and their implication on our jars, and thus I'm wondering if we are using them appropriately. Let me explain what I mean:
When two countries sign a treaty, the fact that there is the signature of a president and a stamp on the piece of paper is enough to consider the treaty valid. When the president or the stamp of a country change, the treaty does not have to be re-signed. The simple fact that the individuals and their tools (stamps) involved in the signature were authority at the time are sufficient to guarantee that the treaty will be valid forever.

Now, if the treaty is the jar and the stamp is the signature created by the certificate, I don't understand why a jar that has been signed with a valid certificate can become invalid or expire. 

Therefore my question, do we use certificate and signature correctly?
Comment 12 Pascal Rapicault CLA 2012-05-24 20:13:19 EDT
Of course adding an option to not complain when invalid signature is encountered would be easier :)
Comment 13 Matthew Piggott CLA 2012-05-25 09:53:46 EDT
I think the difficulty is that there isn't a secure way of determining when a jar was signed.  If dates were ignored and the Eclipse certificate was compromised then jars could be signed indefinitely with the compromised certificate. (Certs can also be revoked, but that hasn't been effective for web browsers.)
Comment 14 John Arthorne CLA 2012-05-25 10:31:09 EDT
(In reply to comment #13)
> I think the difficulty is that there isn't a secure way of determining when a
> jar was signed.

Yes there is. There is a trusted timestamp authority which provides authenticated timestamps (http://www.ietf.org/rfc/rfc3161.txt). We use this at Eclipse (see bug 263708). Our existing signatures *are* still valid after the certificate expires. I think the jarsigner tool just spits out this information because it might indicate you need to renew your certificate. The message does not mean that the signature is invalid. We're all fine here.
Comment 15 Pascal Rapicault CLA 2012-05-25 20:26:16 EDT
John, if the signature are still valid, have we ever looked into changing the signature verification (which I believe equinox own) to detect this case and avoid the complaint?
CC'ing tom as he may know.
Comment 16 John Arthorne CLA 2012-05-25 20:47:28 EDT
Are we just talking about the warning that appears in David's jar signing report? I believe this is coming from executing the JDK's jarsigner tool. I don't think an Eclipse end-user would ever see this.
Comment 17 Pascal Rapicault CLA 2012-05-25 20:49:45 EDT
Given David initial description I thought we were talking about a p2 generated message, but maybe I'm getting that wrong.
Comment 18 Pascal Rapicault CLA 2012-05-25 20:50:56 EDT
Created attachment 216323 [details]
screenshot of the pb
Comment 19 David Williams CLA 2012-05-26 02:20:58 EDT
(In reply to comment #18)
> Created attachment 216323 [details]
> screenshot of the pb

pb? Problem? I don't see the "not signed" warning in that image. Only the "already installed" grayed out icon? Or are my eyes going out on me? 

I don't think "signed or not" can be detected until you try and install something. And, expired certificate but valid at time of signature is not treated as "unsigned" (or give warning) with equinox. There might be a "strict" option you could turn on to make it report those, but not that I know of. 

The "warnings" that people are seeing/talking about are for the straight "jarsigner -verify" reports I create, such as 

http://build.eclipse.org/juno/simrel/reporeports/reports/verifydiroutput/verified.txt

(I should probably right an equinox app to check signatures :) 

BUT, the reason this came up, was someone suggested, "if you really wanted to get rid of the warnings, you can just sign the jar again, you do not need to rebuild it" and in response I then gave the tired warning of "well, if the bits change in anyway the qualifier should change" or users (or, some adopters, that "pull" bits with p2) won't get the newly signed bundle. 

And, all that just reminded me of this issue. I still think _requiring_ the qualifier to change, even if just resigned, is sort of impossible to do. 

Such as, in an ideal case, a company could "resign" our bundles with their own certificates, to stamp them as "these are in same form as when they came from company X product" ... but ... users would never "get" those versions, since qualifier would not have changed (if they already had some installed). 

And to confirm what John said, yes, besides have a steady source of income :) the security companies do claim that "should have limited life time since the longer a certificate/signature is out there, the higher the chance someone would have stolen the key or cracked the code, so best to renew every now and then". 

I have seen in my internet searches, there are some programs or settings that can be ran in "strict" mode, that would not accept jars as valid, even if cert was valid at time of signing ... but, I suspect that's mostly for banks using applets, or something. I've never heard of a real use case. 

The only hint I got of a problem is that you might not be able to resign a code bundle with and additional certificate, if one of its authenticating certs has expired, but a) very hard to find good documentation about this sort of thing, and b) not sure anyone is doing that with our bundles?
Comment 20 Pascal Rapicault CLA 2012-05-26 10:40:48 EDT
Ignore comment #18. Wrong bug.
Comment 21 Thomas Watson CLA 2012-05-29 08:40:18 EDT
(In reply to comment #15)
> John, if the signature are still valid, have we ever looked into changing the
> signature verification (which I believe equinox own) to detect this case and
> avoid the complaint?
> CC'ing tom as he may know.

I believe this has already been answered, but I will reconfirm.  The Foundation uses signs with a TSA and the framework validates it when verifying a signed bundle.
Comment 22 Lars Vogel CLA 2019-11-14 03:28:20 EST
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

If the bug is still relevant, please remove the "stalebug" whiteboard tag.