Make the group-key identifier a content fingerprint

GroupKey.Bytes() returned only {len(A), len(BTilde)} — the dimensions,
which every key of one parameter set shares — so two independent group
keys carried the identical identifier 0808. Anything keyed on it (a
registry, a route, a cache) treated every Corona group as the same
group. Return sha256 of the canonical serialization instead, so distinct
keys have distinct identifiers.

Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
2026-08-21 11:16:52 -07:00
co-authored by Hanzo Dev
parent 8a58c67ebb
commit 04340b42c2
2 changed files with 38 additions and 3 deletions
+12 -3
View File
@@ -13,9 +13,10 @@
package threshold
import (
"fmt"
"crypto/rand"
"crypto/sha256"
"errors"
"fmt"
"io"
"math/big"
@@ -78,8 +79,16 @@ func (gk *GroupKey) Bytes() []byte {
if gk == nil || gk.BTilde == nil {
return nil
}
// Return size info as a simple representation
return []byte{byte(len(gk.A)), byte(len(gk.BTilde))}
// A content fingerprint over the canonical serialization, so distinct group
// keys have distinct identifiers. The previous value was only the (A, BTilde)
// dimensions, which every key of one parameter set shares — anything keyed on
// it collapsed every Corona group into one.
canonical, err := gk.MarshalBinary()
if err != nil {
return nil
}
sum := sha256.Sum256(canonical)
return sum[:]
}
// KeyShare holds a party's secret share data.
+26
View File
@@ -4,6 +4,8 @@
package threshold
import (
"bytes"
"crypto/rand"
"testing"
)
@@ -248,3 +250,27 @@ func TestInvalidThreshold(t *testing.T) {
t.Errorf("expected ErrInvalidPartyCount, got %v", err)
}
}
// TestGroupKeyBytes_IsAContentFingerprint pins that the group-key identifier
// distinguishes distinct keys. It was only the (A, BTilde) dimensions, which
// every key of one parameter set shares, so anything keyed on it collapsed
// every Corona group into one.
func TestGroupKeyBytes_IsAContentFingerprint(t *testing.T) {
_, a, err := GenerateKeysTrustedDealer(1, 2, rand.Reader)
if err != nil {
t.Fatal(err)
}
_, b, err := GenerateKeysTrustedDealer(1, 2, rand.Reader)
if err != nil {
t.Fatal(err)
}
if bytes.Equal(a.Bytes(), b.Bytes()) {
t.Fatalf("two distinct group keys share the identifier %x", a.Bytes())
}
if !bytes.Equal(a.Bytes(), a.Bytes()) {
t.Fatal("group-key identifier is not stable across calls")
}
if len(a.Bytes()) != 32 {
t.Fatalf("identifier length = %d, want a 32-byte content hash", len(a.Bytes()))
}
}