-
Notifications
You must be signed in to change notification settings - Fork 911
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Validate signatures of builds #241
Comments
What about calling out to an external GPG process, like |
This is what the gpgme bindings do effectively. |
cc #242 |
@DemiMarie I'd rather not do that because we can't guarantee the presence of GPG, and I want everybody to get the advantage of signature validation. |
👍 This should not be optional, preventing downgrade attacks. |
https://pijul.org/openpgp/ may be part of the solution. |
Anything involving GPG will have to be optional. |
Ok, after writing both Thrussh and the OpenPGP crates, here are some thoughts:
This is a GnuPG issue. The binary called GPG changes name with different versions (which leads to really unstable situations in systems like NixOS, where it's normally called gpg2, but also sometimes gpg inside a nix-shell, depending on the channel). First of all, I am really grateful to the the authors of OpenPGP and GnuPG for getting the world to use encryption and signatures in an almost easy way. That said, I also realize that RFC 4880 is really unclear and ambiguous, even on really important things. GnuPG has the merit of being the main available implementation. It's also well tested and robust (despite being 200000 lines of C, not counting crypto). However, according to my tests, GnuPG does not always include cryptographically important parts of OpenPGP, such as "modification codes", an OpenPGP feature described in the RFC, which are more commonly called MAC in other cryptography libraries. This might allow an attacker to modify an encrypted message without decrypting it. If we try to implement OpenPGP in Rust, there are really big issues with the format, which IMHO do not make it suitable to use in applications such as rustup:
Btw, I realize there are lots of awesome C programmers out there, and the authors of the above mentioned software are clearly among them. |
Btw, I'm currently thinking of a format with the same features as PGP (a web of trust using the existing infrastructure, encryption and signatures). |
I don't think a web of trust makes sense for rustup. You have to trust on first use anyway, so it seems much simpler and more straight forward to just use TOFU. |
@vks: Before writing the OpenPGP crate, I used to believe this wasn't the case (maybe I've attended a Rust conference and signed the rustup key), and used to think that the web of trust was really cool. I'm not so sure anymore. Here is some arguments: |
It's an issue for any method which attempts to use a user's existing web of trust to validate downloads: it's unrealistic to have that as a prerequisite to install toolchains via rustup. As far as I'm concerned, the plan was always to just encode the public key inside the rustup binary, and have a pure-rust solution to verify the signatures of downloads against that public key. The "web of trust" only comes into play for someone installing rustup for the first time, and if they're doing that via their package manager, then even that's unnecessary. |
I see. Then the best method seems to be:
This doesn't solve everything, though: when the key or the cryptosystem is compromised, you'll have to "revoke" the key. |
While that certainly does not hurt, I don't think it is necessary. The first time you install rustup, you have to trust the binary anyway (unless we get reproducible builds). So you have to trust that the rustup server and your https connection to it are not compromised, and that you get the right rustup binary with the correct hardcoded key. I don't think revocation is a problem with TOFU (see ssh). You would have to just get the new key via https. |
I'd advocate for adopting The Update Framework for verifying the security of rust distributions. There are numerous advantages of the The Update Framework especially semantics for key rotation, the use of only strong cryptography in the spec and json format data files etc. The Update Framework was designed specifically for the relevant use case of securing software distributed through a repository. |
Yeah that is my expectation. I don't know any other solution that can work in practice. We can't expect users to do any manual steps beyond clicking something on our website. rustup.sh did this while still using GPG though - it just told it which keys to use.
Yes, thanks for mentioning that. Key revocation is important. @zmanian Thanks for bringing that to my attention. Looks very promising. We should consider it stongly. Thanks for all the great feedback, all. |
I've gathered up some code for this in https://github.com/djc/rust-sign/blob/master/src/main.rs; I think this provides pretty much all the pieces required. Integrating this into rustup.rs will require more context/design, I guess? |
@djc We might want to have something more complex like The Update Framework mentioned above. |
@vks that's not really a helpful response, in that (a) you're suggesting the work I did has little to no value, and (b), you're not providing a clear way forward. I came here via @brson's someday list thread and implemented the thing he mentioned there (using ring to sign/verify with Ed25519). Clearly, to be useful, this needs to be integrated into rustup.rs. Clearly, that's not what I've done in the rust-sign repo. Still, the code in the rust-sign repo provides most of the crypto-related pieces of Ed25519 signing and verification, so I believe it provides some value. I might be able to contribute more of my expertise and/or time here, but, as I said, I don't think I can do so unless more context/design/direction is provided. |
Oh, and it seems that The Update Framework predates the JOSE (JSON crypto) family of IETF RFC's, so at least some of the ways the spec does crypto feels a bit antiquated. It might be better to adopt the roles and process from TUF without going by the letter of the spec. |
@djc You were asking for more context/design, and I think TUF provides this. In no way did I intend to suggest your work had little value or to provide a clear way forward. |
@djc Thanks for putting that together! This looks like a great basis to work off of. Offhand I don't have a full design to suggest, and I need to read the TUF documentation still, but unless it seems strongly unadvisable I'm inclined to keep a pure-Rust solution, so maybe we can do a design influenced by TUF, even a standalone TUF-like library that all Rust programs can take advantage of. There are a lot of pieces at play in Rust distribution. This is just a brain-dump of how things work today and the binaries that need to be verified:
I'm strongly interested in rewriting the entire release build process, but it seems unlikely to happen soon. So lots of complex legacy stuff to accommodate. To make this more concrete, what I might expect the data used by rustup to end up looking like on static.rust-lang.org, based on how things are organized today, is:
This is all of course open for debate. An interesting thing to note here is that the sigs are stored in two different ways: in the "current.toml" files they are in toml keys in the file and are signatures of other toml keys; in other cases they exist next to the complete files they are signing. Though I think putting signatures next to the bins is a generally good forward-compatible strategy with any changes to the way we might treat the manifests in the future. We could also consider embedding signatures of the tarballs directly in the manifests, though that doesn't work in a straightforward way for the manifests themselves. I'm sure there's lots more to consider. |
How do you guys like rsaltpack? It implements saltpack's encoding of MessagePack format using sodiumoxide. |
@brson What do you think are the next atomic steps to moving this forward? Should we formalize what information the build system should publish? |
I think we should figure out how/how much the update framework applies to the rustup ecosystem, determining what abstract elements we should implement. Then, the next step could be figure out a design for making those abstract elements concrete. |
I made an irlo thread describing how I imagine solving several problems in the rustup distribution format: https://internals.rust-lang.org/t/future-updates-to-the-rustup-distribution-format/4196. It includes a scheme for integrating TUF. |
I LOVE this!!!! The biggest advantage of having a portable TUF implementation with a C API I would also like to see TUF applied to Cargo. On Oct 13, 2016 1:34 PM, "Brian Anderson" [email protected] wrote: The ideal way to implement TUF might be to create a Rust API, create a C — |
@DemiMarie Unrelated to this specific issue, but for your information migrating OPAM to use TUF is a long-standing goal of the OPAM devs, has had received active development effort and is on the roadmap for v2.0. |
This sounds great. If there's any tension between a library usable from other languages, and a generic crate easy to use in Rust, I guess I'd vote for the second one. My specific use case is Pijul: many projects are distributed as git repositories today (like NixOS), and being able to sign these using TUF would be really cool. |
@pijul be sure to sign SHA-2/Blake2b hashes of a Merkle tree, not the SHA-1 hash that Git does on its own (so you will need to do the hashing yourself). |
Argh a TUF implementation was something I was interested in doing before I ever wrote a line of Rust. Even met with the TUF authors, and this benefit of a Rust implementation was definitely interesting to them. But then I went nowhere with it. Perhaps it's less intimidating to start with Rust updates as a much narrower use case than Crates.io... |
It looks like I can't personally devote any time to implementing TUF in the near future, but I'd encourage anyone else to start on it. |
Work on a Rust TUF is going on here. |
@zmanian oh wow thank you! Excited to see where it goes. |
Oh hai @brson. Checking in here to say that I'm almost done with delegations on Anyway. Is there a roadmap or plan to get this implemented? Because it requires some work on the maintainers' side like setting up keys and whatnot. |
@heartsucker, @alexcrichton and I had a chat about tuf integration. Here are the scattered notes for future reference: https://public.etherpad-mozilla.org/p/rustup-tuf |
@brson Would it be possible for you to make a milestone / project here for collecting issues related to this? There are some tasks that I might be able to delegate for this. I think one of them that I could offload to someone else would be update to hyper 0.10 since that's the version |
There is additional discussion of the particulars of the TUF implementation on issue #1217. |
Has anyone yet mentioned or thought of using using signify (originating from OpenBSD IIRC)? |
Can we just use libsodium? Portable. Simple. Fast.
…On Feb 22, 2018 6:33 PM, "Katze" ***@***.***> wrote:
Has anyone yet mentioned or thought of using using signify (originating
from OpenBSD IIRC)?
There seems to even be a Rust implementation
<https://docs.rs/crate/signify/0.4.1> (docs contain various links).
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#241 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AGGWByv2C3LA4WXtIO1XKpfd7-0UENLpks5tXflBgaJpZM4H9Zcu>
.
|
The point of using TUF is that it provides strong security properties from the metadata outside of just "we used a good signing scheme / hash algorithm." Signify and libsodium do not provide that. |
I haven't read through the entire thread, but just since it wasn't mentioned yet: If you want to verify PGP signatures, there's now Sequoia, written in Rust! Not sure how that is useful in context of TUF though, hope this comment isn't just useless spam. |
@dbrgn Sequoia looks interesting (I've been following it for awhile), but it seems like Regarding OpenPGP + TUF, I have been in contact with the TUF developers about this particular problem. I would like to work with them to develop a solution that can allow PGP v4 key IDs to be used in place of TUF's own native key ID format, and OpenPGP signatures as the signature format. I wrote up an initial proposal for that as part of this crates.io signing + TUF design: |
Rustup has been quietly verifying GPG signatures on channel downloads for some time now. I'm going to close this, although there's still the trust chain consideration I think other issues cover that quite well. |
@kinnison does it fail if the signatures cannot be obtained or verified? |
@DemiMarie Currently it warns, though nobody has reported the warning showing up. We intend to shift it to an error soon. |
Is there a way to force it to error? |
What is the issue that tracks that? I thought it was this one. There should be an open issue until it is fixed. |
The high level tracking issue is here - #2028 and I've updated it with the current state of play AIUI. If you feel I should reopen this issue as well for tracking that then I'm okay to do so. |
Right now the rust binaries are accompanies by gpg signatures, but rustup does not check them.
I don't want to bring in native dependencies unless they are dead simple to build. We should probably try the gpgme bindings first, since those would be compatible with our existing gpg keys. If that doesn't work out then we can explore more exotic options.
Previous thread.
The text was updated successfully, but these errors were encountered: