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.

Attachment: signature.asc
Description: PGP signature

Reply via email to