git-bug / git-bug

Distributed, offline-first bug tracker embedded in git, with bridges
GNU General Public License v3.0
8.12k stars 266 forks source link

Identity management: step two #130

Open EclectickMedia opened 5 years ago

EclectickMedia commented 5 years ago

With user's becoming a thing in the codebase, I thought it would be cool to utilize git's gpg signed commit features to allow a user to "prove" their identity via public key.

Having user functionality is wonderful, but what is to stop someone from "adopting" the key of a repository maintainer? Using gpg signatures gives a git native method of verifying who said what on the timeline.

This is defeated however if there is already a system in place for handling identity verification.

MichaelMure commented 5 years ago

Yes, that's the general idea. I haven't written much about it, but here goes the gist:

There is a few design decision to be made:

TODO is:

  1. [ ] implement identity edition (mostly a matter of UI/UX, core is ready)
  2. [x] implement the storage of public keys in the identities + UI/UX to interact with
  3. [x] design & implement the storage of the corresponding private keys somewhere in the system
  4. [x] implement commit's signature verification for git-bug data
  5. [ ] implement basic role checks (only the author can edit his comments)
  6. [ ] implement more complex roles
MichaelMure commented 4 years ago

Some of this is happening in https://github.com/MichaelMure/git-bug/pull/376

MichaelMure commented 3 years ago

Still a lot to do, but git-bug's core can now store/load crypto keys and check signatures.

smoyer64 commented 1 year ago

Per our digression in #963, I wanted to add a few comments related to a) actually signing commits (and as stated above identities) and impacts that this might have on the bridges.

a. It's been a couple of years since I worked on GPG in Go but my recollection is that none of the Go libraries implements the new keybox storage for private keys. My recollection is that GPG generates all new keys into the keybox and that GPG never reads the value of the key (in normal operation - export does). Instead, GPG requires the use of the gpg-agent (which will be started if it isn't already started) and that all signing, verifying, encrypting and decrypting will be delegated to the agent. The main idea is that operations requiring a private key aren't executed by the user's GPG program but rather by an already running/trusted service. In my case (my private keys are on my Yubikeys), I believe there's a marker in the keybox that indicates the scdaemon should be used for the actual value (but this is still handled by the agent). In short (haha), this would tend to contradict the bullet above that states:

design & implement the storage of the corresponding private keys somewhere in the system

b. The other problem I see with the above is that when a bridge is importing an identity, it should NOT have access to the private key to sign the created (or updated) identity - and yet it needs to create the users and make sure they're not adopted by the wrong user even without those signatures. I'm also wondering about the "protection rules" above - are there any vulnerabilities to a user who manually edits their project's .git/config file or uses git plumbing commands?

MichaelMure commented 1 year ago

Shot answer: I don't think those are issues, just some area in the design that need more than a naive thinking.

Disclaimer: I never used GPG so it's a bit uncharted territory for me.

design & implement the storage of the corresponding private keys somewhere in the system

What I meant by that is really just "the private key is not stored in the git entity, only the public key". After that, where and how the private key is stored doesn't matter, as long as we are able to:

  1. sign git commits
  2. verify git signatures

Note: those requirements don't imply that we have access to the private key. It would be perfectly reasonable to have those operations happening externally to git-bug, in the agent or a yubikey. I just implemented that part a bit naively for now.

As for the identity data structure, that would mean we would store there only some kind of identifier for the private key (fingerprint, ...), to be able to search it on the user system. Once found, git-bug should make sure that it's indeed the key matching the public key.

As for the actual code that would do that, my recollection matches yours. It might be difficult to find code that allows us to have this working easily, with great and transparent UX, and able to reach whatever the user normally use.

b. The other problem I see with the above is that when a bridge is importing an identity, it should NOT have access to the private key to sign the created (or updated) identity - and yet it needs to create the users and make sure they're not adopted by the wrong user even without those signatures.

My thinking about this is that a bridge would only:

Once the identity is protected, the bridge can't touch it anymore. This could be a little weird but I suppose that's an acceptable UX if we consider that identities "live their lifes" in git-bug once imported. Possibly we can add the following for completeness:

I'm also wondering about the "protection rules" above - are there any vulnerabilities to a user who manually edits their project's .git/config file or uses git plumbing commands?

Obviously more pair of eyes on this would be great but I think it's OK? Let's try to unpack some obvious scenario:

  1. Bad actor want to adopt an unprotected identity

This one is obvious: it's unprotected. Nothing prevent anyone to do that. Add a public key.

  1. Bad actor want to adopt a protected identity with a single commit

In the data structure would be a single version, with one or more public key, without a git commit signature. There is no proper crypto signature, yet we have a hash of the full payload, that include the public key.

Now, once we have a matching private key, it would make sense to add a properly signed commit, just as precaution. Which brings us to ...

  1. Bad actor want to adopt a protected identity, with more commit(s) after the one introducing the public key

In the data structure would be 0+ commit without public key, followed by 1 commit with 1+ public key, followed by 1+ commit signed by a key present and valid in the previous commit.

Most of the previous reasoning still apply:

The big difference is that it's now possible to have that identity non-uniformly replicated in the git remotes. There is actually two sub-scenario here:

  1. someone push incomplete changes, either only entities updates or only identity updates. This really shouldn't happen as a git push either succeed or not and we are (since recently) pushing all changes in one go. FYI: once the push is done, git-bug fully "import and accept" the identities changes first, for the simple fact that we want to have all identities around before proceeding with the rest.
  2. in a network of remotes, some remotes have one version of the identity, some other have another (older or younger). We won't consider here the case where the author makes, from a V1 identity version, a V2 on one machine and a v2' on another. That would create a network partition and ... just don't. It's a separate issue, due to identities requiring a purely linear chain of commits instead of accepting a DAG (https://github.com/MichaelMure/git-bug/blob/95911100823b5c809225d664de74ad2d64e91972/cache/identity_subcache.go#L28-L33).

IMHO the scenario 1 is unrealistic, so onward for scenario 2:

// TO BE CONTINUED, I'M HUNGRY

github-actions[bot] commented 1 month ago

This bot triages untriaged issues and PRs according to the following rules:

To remove the stale status, you can: