
Signing .jars is not worth the effort - nurettin
https://quanttype.net/posts/2020-07-26-signing-jars-is-worthless.html
======
philips
A solution I am working on for these sorts of software supply chain attacks
uses transparency logs. Take a look here (warning, __alpha
__):[https://github.com/transparencylog/btget](https://github.com/transparencylog/btget)

Essentially the binary transparency log acts like a notary service. It appends
the cryptographic digest of a URL to an append only log. The append only log
cannot be rewound without detection by clients. And clients verify the
contents they receive against the entry in the log.

Two nice properties for the issues outlined in this post:

1\. Hosting providers (or third parties) can add this sort of log without
needing developers to do things like manage key material or 2FA tokens 2\. It
is complementary to good upload authentication or signing systems

In fact, Go is using transparency logs for source libraries. I think similar
systems should be used for binaries in all other language ecosystems as well.

I would love to see a world where major source code distributions start
running transparency log servers as part of their own file host integrity
protections. Imagine maven, github, npm, etc all running these sorts of
services for all uploads and using them by default in their clients. Users
would have additional confidence that the v0.4.3 package they downloaded to
their system two weeks ago is the same one their colleague got or the CI/CD
system got.

~~~
ithkuil
Some time ago I made a fun hack where I abuse the Go transparency log to store
immutable url->fingerprint mappings of arbitrary urls:

[https://github.com/mkmik/getsum](https://github.com/mkmik/getsum)

Example:

    
    
        $ getsum https://github.com/bazelbuild/bazel/releases/download/3.4.1/bazel-3.4.1-installer-linux-x86_64.sh
        9808adad931ac652e8ff5022a74507c532250c2091d21d6aebc7064573669cc5
    

now, if somebody ever replaces that file on github, getsum will fail with an
error.

(I was too lazy to make getsum actually download the file if the checksum
matches, but that should be trivial; for now just do "getsum $url && wget
$url").

This works by creating synthetic Go modules that embed "facts" about URLs
inside generated Go code, which gets then downloaded by getsum and parsed
using the stdlib "go/parser" package. Since all Go modules are recorded in the
Go "sumdb" public transparency log, once this module has been generated it
cannot ever change. (Getsum uses a constant "version" for the synthetic
packages, thus facts are immutable).

I'm confident this works because it piggy-backs on the stable production
transparent logs infrastructure of a high-profile project managed by a high-
profile company. On the other hand the Go transparency logs admins could ban
my "getsum.pub" domain if the generated traffic bothers them. This was for me
just a quick way to show to some colleagues the potentials of transparency
logs etc, and of course to have fun.

~~~
dependenttypes
> (I was too lazy to make getsum actually download the file if the checksum
> matches, but that should be trivial; for now just do "getsum $url && wget
> $url").

Please don't. Instead check the hash of the local file. A malicious server
could serve a different file for getsum and for wget (bonus point: you won't
have to download it twice)

~~~
ithkuil
yes that's indeed a problem that needs to be dealt with.

That said, technically the getsum client doesn't download the file; it only
fetches "$url.sha256" if present or a "SHA256SUMS" in the same directory and
compares that with the one stored in the transparency log.

It follows a common pattern on release sites (such as major projects on
github).

In other words getsum only ensures that the checksum file itself is immutable,
and the checksum file then is used to ensure that bigger file also hasn't
changed. The reason for that lies in the fact that getsum has a server side
component (hosted on getsum.pub) that serves the Go modules fetched by the Go
sumdb.

Thus, the correct instructions are:

    
    
        $ (echo -n $(getsum https://github.com/bazelbuild/bazel/releases/download/3.4.1/bazel-3.4.1-installer-linux-x86_64.sh); echo " bazel-3.4.1-installer-linux-x86_64.sh") > bazel-3.4.1-installer-linux-x86_64.sh.sha256 && wget https://github.com/bazelbuild/bazel/releases/download/3.4.1/bazel-3.4.1-installer-linux-x86_64.sh && sha256sum -c bazel-3.4.1-installer-linux-x86_64.sh.sha256
        
    

Big file downloaders tend to be more complicated than expected; progress bars,
resuming downloads etc etc. Perhaps getsum instead of downloading the file it
could verify the file? E.g.:

    
    
        $ wget https://github.com/bazelbuild/bazel/releases/download/3.4.1/bazel-3.4.1-installer-linux-x86_64.sh && getsum -c bazel-3.4.1-installer-linux-x86_64.sh https://github.com/bazelbuild/bazel/releases/download/3.4.1/bazel-3.4.1-installer-linux-x86_64.sh
    

EDIT: just implemented the "-c" flag described above

------
compsciphd
Here's an aside / funny thing about jar signing on blurays. The Blu-Ray spec
only really enforces jar certificate verification for encrypted blurays (i.e.
AACS). non AACS blurays (i.e. decrypted), ignore the certificate chain. i.e. a
self signed certificate that uses its own key to sign the jars works fine per
the spec.

The only reason people can take blurays (with java menus) and make them
reliably playable when decrypted (in real players, ignoring things like VLC
which can easily ignore the cert chain) is because the bluray spec tells them
to explicitly ignore the certificate chain. This enables decryption programs
to rewrite the java bytecode (and resign the jar's with a self signed
certificate) removing any protection mechanisms (think screenpass) that are in
the java code itself.

While I sort of understand the reason for it (you want to be able to test
discs before mastering without encryption and without the need for signing),
it really killed what could have been an effective security model. Basically
the standard strong security vs convenience dilemma.

~~~
AnthonyMouse
I half suspect they do things like that on purpose, because the alternative is
to create demand for players that disregard the restrictions, and by that
point they're also going to disregard all of the other ones and let the user
fast forward through commercials etc.

So if they let the thing they don't want people to do be hard but not too
hard, it satisfies demand from the people determined to do it instead of
creating a market to solve the problem which would make it _more_ convenient.

~~~
compsciphd
I don't know. perhaps, but they've shown a large willingness to force the
hardware players to enforce security mechanisms that can't really be avoided
nicely (ex: cinavia, there are ways to avoid it, but very few on disc based
players)

------
CamouflagedKiwi
I've thought this about Maven Central before (not familiar with Leiningen, but
it seems it's trying to do a similar thing).

Maven Central has PGP signatures for all uploaded artifacts - but they are in
fact useless, because anyone can create a PGP key that claims to be (say)
maven-releases@google.com and upload that to a keyserver. There appears to be
no mechanism by which a consumer can know whether the signing key should be
trusted, so an attacker uploading a malicious artifact can easily upload a
malicious signature with it.

I'm not going to argue with any of the criticisms of PGP in the linked
article, but they don't seem hugely relevant to the problem here; the
fundamental trust problem is much deeper than "GPG has janky code" (and it's
not like there aren't any other options at all).

~~~
WatchDog
Maven central will let you sign artifacts with any published key you like, but
one thing you can do in theory, is verify that new releases are signed by the
same key as a known good release. I am not aware of anyone actually doing this
though.

~~~
yarg
That approach is still vulnerable to what amounts to a MITM attach: a bad
actor can simply provide the legitimate versions for whatever period he deems
required to build trust.

------
MaxBarraclough
> As far as I know, nobody ever verifies the signatures in a systematic way.

If you'll forgive a semi-relevant ramble about SSH:

The situation seems similar with SSH. As far as I can tell, just about
everyone goes with the approach of trust-blindly-on-first-use. I've made a
habit of manually checking the public-key when I SSH into a new EC2 instance
using PuTTY. It is not obvious how to do this. Existing tooling just isn't set
up with it in mind.

The fingerprint reported on the EC2 system-log uses a different hash function
than PuTTY uses. (This is PuTTY's fault. It's behind OpenSSH.) I was able to
get an answer on ServerFault, but I was surprised no-one had asked the
question before. [0]

With some lesser-known distros it seems to be outright impossible, as the
fingerprint is not written to the system-log at all. Presumably the distro
maintainers never check SSH fingerprints.

Still less relevantly: the trust-blindly-on-first-use antipattern is known
euphemistically as _TOFU_ , for _trust on first use_. This term can also refer
to where the public key is manually verified by the user on first use. [1]
Very unhelpful for a term-of-art to be so ambiguous.

[0] [https://serverfault.com/q/996828/](https://serverfault.com/q/996828/)

[1]
[https://en.wikipedia.org/wiki/Trust_on_first_use](https://en.wikipedia.org/wiki/Trust_on_first_use)

~~~
forty
SSH certificates avoid this issue and are used in real life. We make them with
hashicorp vault, it works well and is really convenient.

~~~
GordonS
Huh, I had no idea there was even such a thing as SSH certificates!

Presuming you mean X.509 certificates, is this part of the standard spec (e.g.
should work with OpenSSH etc)? Do you know if it works with PuTTY?

~~~
jbreiding
Here is a guide I've found useful in the subject,
[https://engineering.fb.com/security/scalable-and-secure-
acce...](https://engineering.fb.com/security/scalable-and-secure-access-with-
ssh/).

------
atlgator
Java applets are largely dead at this point but they do still exist in small
corners of the IE world. Signing those jars is paramount and the signature is
validated by the browser.

~~~
johannes1234321
"Java Web Start" still exists and there are at least two programs I use from
time to time based on that technology. One being a custom thing, the other
openstreetmap editor jOSM.

~~~
chrisseaton
> "Java Web Start" still exists

I'm afraid it's been dead for a while now.

> Java Web Start (JWS) was deprecated in Java 9, and starting with Java 11,
> Oracle removed JWS from their JDK distributions.

[https://openwebstart.com/](https://openwebstart.com/)

~~~
zitterbewegung
Just because its depricated doesn't mean it is unused.

People still use Python 2.7.

~~~
chrisseaton
It's not deprecated - it _was_ deprecated and now it's completely gone.

Like Python 2.7, you can now only get support for JWS if you pay or if you go
through a third-party.

If you're still using it I recommend you get off fast.

~~~
sdinsn
> now it's completely gone.

...From newer versions. Old JDK versions have been kept the same, and Java 7 &
8 are still in heavy use.

> you can now only get support for JWS if you pay or if you go through a
> third-party.

Not everyone needs enterprise support.

~~~
chrisseaton
> Old JDK versions have been kept the same, and Java 7 & 8 are still in heavy
> use.

But they aren't getting free security updates.

> Not everyone needs enterprise support.

Run it without security patches? That's _suicidal_ for a system like JWS.

Or do you think there's some option that is still support but not specifically
_enterprise_ and doesn't cost anything? I would take a look at who
historically contributes security patches to OpenJDK and think about if you
free vendor really has the expertise you think they do to keep up with
security attacks.

~~~
sdinsn
> Or do you think there's some option that is still support but not
> specifically enterprise and doesn't cost anything?

Yes, Amazon backports security updates to Amazon Corretto (fork of OpenJDK 8
and 11)

~~~
chrisseaton
> Amazon backports security updates to Amazon Corretto

There's a flaw in your logic there...

JWS is gone in new versions, so there aren't any security updates for it in
the newer versions either.

You can't backport a patch which hasn't been written.

------
lmm
> As far as I know, nobody ever verifies the signatures in a systematic way.

I systematically check the signatures on the jars of my dependencies. See e.g.
[https://github.com/m50d/tierney/blob/master/free/keys.proper...](https://github.com/m50d/tierney/blob/master/free/keys.properties)
. If these artifacts were signed with different keys, I would notice (my CI
builds would fail). There are still points of failure (e.g. if you could
subvert the maven-pgpverify-plugin itself), but security is about increasing
the cost of attacks.

> It’s hard to find the public keys for the library maintainers. Sometimes
> they upload them on the keyservers, sometimes not.

> There’s no established way of communicating that which public keys should be
> trusted. If there’s a new release and it has been made with a new key, your
> best bet is to e-mail the maintainer and ask what is up.

> It’s hard to get any security benefits from the signatures in practice.

This is making perfect the enemy of good. Any solution to this problem would
have to start with a signature mechanism. The signatures that currently exist
make it a little bit harder to fake a library. If you want to make it harder,
check signatures on jars you depend on, ask maintainers to publish their keys
to keyservers and communicate which keys should be trusted, demand
explanations when keys change.

Better to light a candle than curse the darkness. "x is incomplete, therefore
it should be replaced by a completely new thing" is a total fallacy - and,
strangely, seems to be used only when attacking PGP.

------
trishankkarthik
This is why you should use a well-designed system such as The Update Framework
(TUF) that aims to make security as usable as possible:

[1]
[https://www.python.org/dev/peps/pep-0458/](https://www.python.org/dev/peps/pep-0458/)
[2] [https://theupdateframework.io/](https://theupdateframework.io/)

------
Uwqye2134trf
When I work on embedded Linux stuff I sign my packages.

Shipping hardware as opposed to software allows secure deployment of pre-
shared keys which can be trusted.

Even if someone hacks our automatic updates server (not too unlikely, it's
some shared hosting), devices we have sold won't trust the modified packages
because 512-bit ECDSA signature won't match the public key they have pre-
deployed.

~~~
beefhash
Out of curiosity:

1\. Why ECDSA?

2\. Why a 512-bit prime for the curve?

~~~
Uwqye2134trf
1\. Only two asymmetric algorithms are widely supported and almost universlly
recommended, RSA and ECDSA. Compared to RSA, ECC needs smaller keys for same
security.

2\. I did that couple years ago already, I think it actually was 521 bits, the
best one recommanded by FIPS at that time. The hardware has no relations to
FIPS, it's not even _that_ expensive and should contain no secret data. I just
saw no reasons not to implement the best security available: development time
is not affacted by the count of these bits.

------
based2
[https://stackoverflow.com/questions/3307146/verification-
of-...](https://stackoverflow.com/questions/3307146/verification-of-
dependency-authenticy-in-maven-pom-based-automated-build-systems)

[https://issues.apache.org/jira/browse/MNG-6026](https://issues.apache.org/jira/browse/MNG-6026)
Extend the Project Object Model (POM) with trust information (OpenPGP, hash
values)

[https://issues.apache.org/jira/browse/MNG-5814](https://issues.apache.org/jira/browse/MNG-5814)
Be able to verify the pgp signature of downloaded plugins against a trust
configuration

------
upofadown
What's with the random shot at PGP at the end? PGP is perfectly fine for this
particular application. None of the stuff that the article talks about has
nothing to do with the particular tool used to sign the releases.

------
based2
[https://en.wikipedia.org/wiki/Key_server_(cryptographic)](https://en.wikipedia.org/wiki/Key_server_\(cryptographic\))

------
deepersprout
> PGP is bad and needs to go away

how should we sign git commits?

~~~
the_pwner224
There's nothing special about PGP that makes it good for signing git commits,
and plenty of alternatives exist. Signify is a simple tool to do signing, used
by OpenBSD:
[https://news.ycombinator.com/item?id=9708120](https://news.ycombinator.com/item?id=9708120).
Minisign is also an alternative, though it doesn't seem as popular:
[https://jedisct1.github.io/minisign/](https://jedisct1.github.io/minisign/).
These may not be well integrated into git, but aside from 'everyone already
uses and integrates with PGP,' there's no real reason stopping the usage of
these other tools.

The two things that PGP does are pretty simple/straighforward. What makes PGP
bad is that PGP itself it is really complicated, and the way it is integrated
into email etc. is also complicated and carries a _lot_ of historical baggage.
But if you just want to make a public/private keypair and then use it to sign
& encrypt data, that's pretty easy (or as easy as writing any crypto code can
get). Signify, Minisign, and Age are clean, simple implementations.

Age does encryption:
[https://news.ycombinator.com/item?id=21895671](https://news.ycombinator.com/item?id=21895671)

Of course this is sort of a [https://xkcd.com/927/](https://xkcd.com/927/)
situation. PGP is already used by everyone so why switch?

~~~
monoideism
The perfect is the enemy of the good.

\-- Voltaire

OK, if you're going to downvote this, please tell me how you plan to convince
git and Github to replace PGP with signify? Github in particular has invested
significant time building up their PGP support.

Personally, I would be fine with signify, I've used it in the past and I like
it, and I think people are right when they say we should move toward more
focused, Unix-style cryptographic tools - _for greenfield projects_.

But that doesn't we should abandon all current uses of PGP, particularly when
it's working as well as it is with git and Github. There's absolutely nothing
wrong with it. It does what it's supposed to.

It took a long time to get PGP supported by Github, and now you're going to
want them to change it?

Edit: If people want to _add_ support to Git for signify, and lobby Github to
support it, I'd be in favor. But strongly, strongly opposed to removing PGP
support.

~~~
wglb
You might want to check out a couple blog posts

[https://latacora.micro.blog/2019/07/16/the-pgp-
problem.html](https://latacora.micro.blog/2019/07/16/the-pgp-problem.html)

[https://blog.cryptographyengineering.com/2014/08/13/whats-
ma...](https://blog.cryptographyengineering.com/2014/08/13/whats-matter-with-
pgp/)

And don't complain about downvoting.

~~~
monoideism
I'm fine if you think I'm an idiot (I definitely can be), if you disagree with
my stand on PGP, or my remark about downvoting. I'm often even willing to
edit/change/correct my comments.

But don't order me around. I'm not your employee, kid, or whoever it is you
feel you have a right to speak to like that.

------
baybal2
The author made a fundamental mistake of judgement.

So far, what he says amount to an advocacy against digital signing of code as
such.

Miikka Koskinen says "digital signing doesn't work, so, lets decide to use
something even more broken." Just that alone makes me think he has no say on
this.

~~~
derefr
Nah. He said that the current infrastructure for signing JARs _is_ broken,
making _supplying_ signed JARs pointless. He didn’t say that this is the way
things _should_ be.

He advised, at the end, fixing the system; but it is implicit in his tone that
he doesn’t expect anyone to try—it’s been broken this long with nobody caring,
so why would that change now?

And yes, he advised relying on other mechanisms for verification, for the time
being. Because those mechanisms provide nonzero (if small) security, while the
current infrastructure for JAR signing provides zero security.

(Compare: “if calling the police does nothing, at least carry pepper spray.”
This advice does not imply that pepper spray is better than _effective_ police
response; only better than an _ineffective_ one. It also does not imply that
one should not seek police reform. It only suggests what one should do _while_
the condition of “ineffective police response” still holds.)

At the end, he says:

> I’ve written this post in part to be proven wrong. I’m eagerly waiting for
> posts from y’all about how you do, in fact, systematically verify the
> signatures.

One would presume that, if he _were_ proven wrong, and the digital signatures
Of JAR files actually did anything, he would retract this post and post one
giving the opposite advice.

