decred / decred-release

Decred binary releases.
ISC License
86 stars 42 forks source link

Verification of bins and sourcecode #95

Closed karamble closed 7 years ago

karamble commented 7 years ago

I don't know if its the correct place for that issue but a slack user was asking about the verification process. His question was about the verification of the binary and the verification of the toolchain binaries that got installed by dcrinstall.

His main request was to be able to verify the sourcecode. Is there a chance we can enable users to verify sourcecode?

Additionaly i will open an issue on dcrdocs as we came to the conclusion that it would make sense to give guides for system hardening in the documentation.

jcvernaleo commented 7 years ago

I don't know what 'verify the sourcecode' even means. We do provide signatures that prove that the binary files that you download are the ones we posted (and link to the instructions for verifying that with each release).

Unfortunately, there really is no way to go from a compiled binary to the source code that made it. Even decompilers can't really do that. And go does not do reproducible builds exactly (certain artifacts like build path end up in the binary).

We do use glide to make sure the same deps are used in the build and the binaries do show what version of the go compiler I used to build:

jcv@triforce ~ $ dcrd -V
dcrd version 0.8.2-beta+dev (Go version go1.7.5)

Each release is build from a tag so if a user wants they can build their own version of a release. I also include the hash that I built from in the release notes so you could also build from that. If someone is worried at this level, that is really the only thing that they can do. Anything else doesn't provide any extra security and I'm not going to recommend people do things that make them feel good but provide no extra security (thinking you are secure when you aren't is worse than knowing you are insecure).

So in summary, if a user is worried about verifying that things correspond to the sourcecode, then their only option is to build from source themselves. This is really the case with all software (and if you are really paranoid, read the classic trusting trust paper by Ken Thompson https://www.ece.cmu.edu/~ganger/712.fall02/papers/p761-thompson.pdf but that is a whole I do not like going down).

jcvernaleo commented 7 years ago

And just for completeness, here is the doc I link to in each release about confirming signatures: https://github.com/decred/decred-release#verifying-binaries

cwhitney3495 commented 7 years ago

@karamble thanks for opening this issue. Since I want to clarify my point, I made an account to join the conversation.

@jcvernaleo Hi, I'm the user that brought up this issue in the slack channel. I'll try to clarify my point with regard to your response:

I don't know what 'verify the sourcecode' even means. We do provide signatures that prove that the binary files that you download are the ones we posted (and link to the instructions for verifying that with each release).

When I say 'verify the source code', I mean the same thing as 'verifying a binary' but for the source code archive that sits along side the binaries and manifest of a release (e.g. v0.8.2.tar.gz with respect to release decred/decred-release/releases/tag/v0.8.2). I'm certain we both agree that 'verifying a binary' is done by following the clear and precise steps you have helpfully documented here.

Presently, this is what happens when I try to verify the source archive of release 0.8.2 by following the documented steps:

  1. Download the file manifest, the signature for the file manifest, and the the source archive from here.
  2. Obtain the SHA256 value for the source archive and check that it matches the value in the file manifest

Error: I can't check that the SHA256 value of source archive that I downloaded matches the value in the manifest because it isn't present in the manifest.

Why do I want to verify the source archive? For a binary, I want to verify that the binary that was built by the developer on their build machine is precisely the same binary that I downloaded. In other words, I want to make sure that the github server didn't give me something else. I want to achieve the same thing for the source archive: I want to verify that the source code that the developer used to build the binaries is the same source code that I downloaded from the github server. If it's not, I don't want to try to compile it, and I certainly don't want to compile+run it.

I think you can resolve my issue here by adding the SHA256 sum of the source code archive to the signed manifest file. Thanks for any time and effort you can provide to helping me with this.

jcvernaleo commented 7 years ago

There are a couple of problems with this.

First, I do not create that source code archive. That is automatically generated by github at the point that I make the release on the github website. So it is made AFTER I generate the shas that are posted for the binaries. This means that I do not have access to that file at the point things are posted and just as important, it is generated by github and not by me so I would not want to sign it anyway (since I didn't make it).

Also, that source file is created by github based on the repo that you post on at the time you create a release but it has no necessary connection to the files that are attached to the release. For example, if you look in decred/decred-binaries, the files attached to the release are all of our binaries other than the installer, but the source archive is just my build script (since that is what is in the binaries repo). So signing that proves nothing.

Finally, since go does not have reproducible builds (see my previous reply), signing the source does not tell you if it is or is not the source that I used to build the binaries.

If you care about these things (and I'm always happy when someone does) then you need to build from source yourself. Anything I do here will not really give you any additional info/reason to trust things.

The current signatures do prove that github is serving you what I uploaded. It does not prove that what I uploaded was built with the source code I said it was, but if you are worried about that you must build for yourself.

cwhitney3495 commented 7 years ago

Hi @jcvernaleo,

First, I do not create that source code archive. That is automatically generated by github at the point that I make the release on the github website. So it is made AFTER I generate the shas that are posted for the binaries. This means that I do not have access to that file at the point things are posted and just as important, it is generated by github and not by me so I would not want to sign it anyway (since I didn't make it).

Thanks for clearing this up, I wasn't aware of it.

Also, that source file is created by github based on the repo that you post on at the time you create a release but it has no necessary connection to the files that are attached to the release. For example, if you look in decred/decred-binaries, the files attached to the release are all of our binaries other than the installer, but the source archive is just my build script (since that is what is in the binaries repo). So signing that proves nothing.

Ah I see. I've misunderstood what that code does, I thought it would build those binaries that are part of the release.

Finally, since go does not have reproducible builds (see my previous reply), signing the source does not tell you if it is or is not the source that I used to build the binaries.

I disagree here. Since I trust you (via your key), then I trust you not to lie about this. So to me, a signature on some source code hash does tell me what source code you used to build the binaries.

If you care about these things (and I'm always happy when someone does) then you need to build from source yourself. Anything I do here will not really give you any additional info/reason to trust things.

Indeed, I'm having this issue because I'm trying to build for myself. To clarify the issue of trust from my perspective: I trust you and the decred team (which is to say I trust your GPG key), and I'd rather not trust any infrastructure between you and me, if possible. From this perspective, a measurement of the source code you were building from is additional info that is relevant to me.

The current signatures do prove that github is serving you what I uploaded. It does not prove that what I uploaded was built with the source code I said it was, but if you are worried about that you must build for yourself.

Can you tell me (in a way that I can verify with your GPG key) the hash of the source code you (or your script, if that's more accurate) have in hand when you are building the binaries for a release? Since I trust you, I'll simply believe whatever hash you tell me (and you can tell me the hash of an archive file or even a git commit hash). I'm not trying to reproduce your binaries, I'm just trying to obtain certified source code to build from, so that I know I'm building from the same source you had when you built it.

For example, take this file of decred release binaries. It contains:

dcrctl
dcrd
dcrwallet
sample-dcrctl.conf
sample-dcrd.conf
sample-dcrwallet.conf

What if the script that generated this file added a new file, say "build-time-source-code-measurement.txt", that had some content like:

<sha256 of source archive or git commit hash> name of a source archive or "https://github.com/decred/dcrd"
<sha256 of source archive or git commit hash> name of a source archive or "https://github.com/decred/dcrwallet"

Since this file is inside a tar file that is authenticated by these files, I'll know I can trust those references came from you/the decred team. With this knowledge I can go find those source archives or the relevant git repo at that commit, and build for myself.

Could you consider adding something like that to your script? Thanks

PS I want to stress that I'm not trying to reproduce the release binaries bit for bit, I understand that reproducible builds are not possible. If you want, I can explain why I want source code certified by you, but I don't want to waste your time with explanations unless you're interested.

jcvernaleo commented 7 years ago

That source code archive made by github is very misleading. I wish I could disable it but unfortunately, github doesn't give much control over the release pages.

I guess I could include the commits text in the release tarball since that gets signed. https://github.com/decred/decred-binaries/blob/master/release-notes.md#commits

A better solution might be if I sign the tags that I build from: https://help.github.com/articles/signing-tags-using-gpg/ All releases are already tagged and at least one dev (@davecgh already signs his commits). I don't sign most commits since it gets a little inconvenient with our rebase heavy workflow, but signing tags would probably be pretty easy.

How does that idea sound to you?

I can't promise it for the next release since time is getting pretty short to update my workflow for it (although I may try), but I could definitely be signing tags before the one after that.

cwhitney3495 commented 7 years ago

Putting commits in the release tarball and signing the release tag both sound great. I'd appreciate it very much if you could do either or both, as either one will solve my problem. Thanks @jcvernaleo.

jcvernaleo commented 7 years ago

Okay, so after looking into it, signing the tags with git seems like least hacky way to do it (might as well use actually make use of what our tools can do). So from the next release on I will sign the tags that I use to build. github shows that the tag is signed on the website and you can verify on the command line with

git tag -v <TAGNAME>

Thanks for this discussion @cwhitney3495! I think doing this is an improvement over what we were doing.