45mg <45mg.wri...@gmail.com> writes: > Hi Tomas, > > Tomas Volf <~@wolfsden.cz> writes: > >> I do have some ideas regarding how to do it, but all of them are fixes >> intended to solve "authenticating my Guix fork", not general fixes for >> guix-git-authenticate. But I think it can be made to work (sadly it >> will not be pretty though). > > I think I may have an idea myself; one that seems reasonably clean, > would fix our use-case of authenticating our own personal Guix forks, > and would even allow pulling branches from other people's forks and > authenticating those. > > We could allow users to specify additional channel introductions. So, > there's always one primary introduction, but there can also be one or > more additional ones. > > Then, when authenticating commits, we choose the introduction that is > the most recent ancestor of the latest commit, and authenticate that > range. > > For commits that have multiple parents - ie. merge commits - we weaken > the invariant as follows: > > 1. If all parents have the primary introduction as their most recent > ancestor, then the invariant holds as usual. > > 2. If one or more parents has the primary introduction as its most > recent ancestor (call these the 'primary parents'), and the rest have > any of the additional introductions, then the merge commit is > authenticated if and only if: > a) it's signed by a key authorized in all of the primary parents, AND > b) the /first parent/ [^] of the merge commit is a primary parent. > > 3. If all parents have the same additional introduction as their most > recent ancestor, then the invariant holds as usual. > > 4. If none of the parents have the primary introduction as their most > recent ancestor, nor do they have the same additional introduction, > then the merge commit cannot be authenticated. > > [^] Quoting from the Pro Git book [1]: >> ...the first parent of a merge commit is from the branch you were on >> when you merged (frequently master), while the second parent of a >> merge commit is from the branch that was merged...
Problem here is that this (which parent is first) is just a convention that the attacker does not have to follow. Example: --8<---------------cut here---------------start------------->8--- /tmp/xx $ git commit-tree -p HEAD -p HEAD~1 -m M HEAD^{tree} c040e61bc184b5971f68c4b794c3158350b5d5e9 /tmp/xx $ g show c040e61bc184b5971f68c4b794c3158350b5d5e9 commit c040e61bc184b5971f68c4b794c3158350b5d5e9 Merge: 40ef875 17451b8 Author: Tomas Volf <~@wolfsden.cz> Date: Tue Jan 14 23:12:17 2025 +0100 M /tmp/xx $ git commit-tree -p HEAD~1 -p HEAD -m M HEAD^{tree} ec74e368519b667d8d280639db6642b28d37eb53 /tmp/xx $ g show ec74e368519b667d8d280639db6642b28d37eb53 commit ec74e368519b667d8d280639db6642b28d37eb53 Merge: 17451b8 40ef875 Author: Tomas Volf <~@wolfsden.cz> Date: Tue Jan 14 23:12:32 2025 +0100 M --8<---------------cut here---------------end--------------->8--- Notice that I have created two commits, and they have the same parents, just in swapped order. Does this change anything? I admit I have read your email fairly quickly due to real life constraints, and would need to draw a picture or two to make sure I actually understand it. > > The idea is - the primary introduction is for the part of the tree under > YOUR control. When you fork Guix and create your own branch, you use the > initial commit on your branch as the primary channel introduction. You > add upstream Guix's primary channel introduction as an additional > channel introduction. If you add anyone else's fork as a remote and pull > one of their branches, you add their primary introduction as one of your > additional introductions. > > Thus, any merge into one of YOUR branches (ie. any branch with the > primary introduction as the most recent ancestor) only needs to be > signed by a key that's authorized on that branch. > > But you can't merge into a branch from upstream Guix or someone else's > authenticated fork (unless you're authorized to commit to those), > because the first parent of the merge commit would not be a primary > parent (see 2b) - it would be a commit on someone else's branch. And > people not authorized by you can't merge into your branch either, > because of 2a. And finally, you can't merge someone else's fork and > upstream, or anything like that. The merge commit would not be > authenticated in any of these cases. > > What do you think? I don't actually know when I can work on a patch for > this (I've spent far too much time on this issue already), but it'd be > nice to have a sanity check on this anyway, so that if the approach is > fundamentally flawed in some obvious way that I'm missing, then I don't > have to waste my time on it. > > [1] https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection -- There are only two hard things in Computer Science: cache invalidation, naming things and off-by-one errors.
signature.asc
Description: PGP signature