Skip to content
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

Identity management: step two #130

Open
EclectickMedia opened this issue May 2, 2019 · 5 comments
Open

Identity management: step two #130

EclectickMedia opened this issue May 2, 2019 · 5 comments

Comments

@EclectickMedia
Copy link

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
Copy link
Owner

MichaelMure commented May 2, 2019

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

  • identities in git-bug are mutable even after creation, they use a chain of commits (each holding a full timestamped version of the identity) to be editable. The current active version is the last one in the chain, but git-bug can go back in time to check if the rules in a bug are valid with the identity state at that time.
  • each version of the identity store either zero, one or more crypto public key
  • if an identity has zero key, it is unprotected. That means that anybody can use it. This is useful for importers that don't necessarily have a public key at hand.
  • if an identity has at least one crypto key, it is protected. This means a few things:
    • to create a new version for this identity, the new commit must be signed with a key present in the precedent version, otherwise it's rejected
    • all bug editions with this identity must be signed with a crypto key valid at that time. This means that only the author can use that identity.
    • it's not possible to revert back to unprotected
    • key rotation/revocation can be implemented: simply create a new version without the old key and a new one
  • once this key system exist, we can add a permission scheme and roles (example: an admin can edit any comments but normal users can only edit their own)
  • if the keys are the same for git and git-bug, we can start to check commit signature on the normal (code) commits (!)
  • the identity subsystem could possibly be made into a standalone tool (ie, without git-bug) to embed and share public keys inside the git repo to check automatically commit signatures

There is a few design decision to be made:

  • does that should use GPG ? How ? CLI parameters don't seems to be standardized and that can be a pain for multi-platform.
  • should we embed our own GPG implementation ?
  • does those public keys should be published in a public GPG keystore ?
  • should we import keys from GPG ?
  • if/when the webUI start to accept users from external systems, how do we create/store keys for them ?

TODO is:

  1. implement identity edition (mostly a matter of UI/UX, core is ready)
  2. implement the storage of public keys in the identities + UI/UX to interact with
  3. design & implement the storage of the corresponding private keys somewhere in the system
  4. 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 MichaelMure changed the title feat: Global user/"gpg signed users" Identity management: step two May 5, 2019
@MichaelMure
Copy link
Owner

Some of this is happening in #376

@MichaelMure
Copy link
Owner

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

@smoyer64
Copy link
Collaborator

smoyer64 commented Jan 2, 2023

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
Copy link
Owner

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:

  • create an identity without public key (aka unprotected), if no keys are known
  • create an identity with public key (aka protected), if some keys are known
  • update an unprotected identity, either to update identity details or add some public keys (making it protected)

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:

  • update the user protected identity, as the private key is available (could be generalized as "any identity of which we have access to the private key)

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.

  • any update on another entity is required to be signed by one of those keys, so no abuse possible there.
    • if the "same" identity is created on another machine, it would have a different ID, and being able to fake that would require being able to do a hash collision (sha256)
    • as we have a single commit, there is no question of said identity not being fully propagated in the git remotes, it either exist fully replicated or not
  • as git-bug verify that the identity ID is the hash of the full payload, the bad actor can't tamper the payload without changing the ID, which would be dropped by other clients

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:

  • once we have a signed git commit, we have a fully signed chain. It's not possible to tamper anything without having the private key
  • bad actor can't use a leaked private key if the author has updated its identity to remove the leaked key (aka revoked it)

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 (
    // TODO: this is terribly ugly, but we are currently stuck with the fact that identities are NOT using the fancy dag framework.
    // This lead to various complication here and there to handle entities generically, and avoid large code duplication.
    // TL;DR: something has to give, and this is the less ugly solution I found. This "normalize" identities as just another "dag framework"
    // entity. Ideally identities would be converted to the dag framework, but right now that could lead to potential attack: if an old
    // private key is leaked, it would be possible to craft a legal identity update that take over the most recent version. While this is
    // meaningless in the case of a normal entity, it's really an issues for identities.
    ).

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

// TO BE CONTINUED, I'M HUNGRY

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants