Skip to content

Commit

Permalink
handle repository signatures, was more of an adventure than i initial…
Browse files Browse the repository at this point in the history
…ly thought
  • Loading branch information
whyrusleeping committed Feb 10, 2023
1 parent 7c05947 commit ab83a33
Show file tree
Hide file tree
Showing 23 changed files with 285 additions and 163 deletions.
5 changes: 2 additions & 3 deletions api/plc.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"net/url"
"strings"

key "github.com/bluesky-social/indigo/key"
did "github.com/whyrusleeping/go-did"
otel "go.opentelemetry.io/otel"
)
Expand Down Expand Up @@ -63,14 +62,14 @@ type CreateOp struct {
Sig string `json:"sig" cborgen:"sig,omitempty"`
}

func (s *PLCServer) CreateDID(ctx context.Context, sigkey *key.Key, recovery string, handle string, service string) (string, error) {
func (s *PLCServer) CreateDID(ctx context.Context, sigkey *did.PrivKey, recovery string, handle string, service string) (string, error) {
if s.C == nil {
s.C = http.DefaultClient
}

op := CreateOp{
Type: "create",
SigningKey: sigkey.DID(),
SigningKey: sigkey.Public().DID(),
RecoveryKey: recovery,
Handle: handle,
Service: service,
Expand Down
8 changes: 4 additions & 4 deletions api/plc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import (
"fmt"
"testing"

key "github.com/bluesky-social/indigo/key"
"github.com/lestrrat-go/jwx/jwk"
did "github.com/whyrusleeping/go-did"
)

type testVector struct {
Expand Down Expand Up @@ -88,12 +88,12 @@ func TestPLCCreateVector(t *testing.T) {
t.Fatal(err)
}

mk := key.Key{
mk := did.PrivKey{
Raw: &spk,
Type: "P-256",
Type: did.KeyTypeP256,
}

if mk.DID() != tv.Did {
if mk.Public().DID() != tv.Did {
t.Fatal("keys generated different DIDs")
}

Expand Down
5 changes: 3 additions & 2 deletions bgs/bgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,13 +175,14 @@ func (bgs *BGS) handleFedEvent(ctx context.Context, host *models.PDS, evt *event

u = new(User)
u.ID = subj.Uid
u.Did = evt.Repo
}

// TODO: if the user is already in the 'slow' path, we shouldnt even bother trying to fast path this event

if err := bgs.repoman.HandleExternalUserEvent(ctx, host.ID, u.ID, evt.RepoAppend.Prev, evt.RepoAppend.Ops, evt.RepoAppend.Car); err != nil {
if err := bgs.repoman.HandleExternalUserEvent(ctx, host.ID, u.ID, u.Did, evt.RepoAppend.Prev, evt.RepoAppend.Ops, evt.RepoAppend.Car); err != nil {
if !errors.Is(err, carstore.ErrRepoBaseMismatch) {
return err
return fmt.Errorf("handle user event failed: %w", err)
}

ai, err := bgs.Index.LookupUser(ctx, u.ID)
Expand Down
18 changes: 12 additions & 6 deletions carstore/repo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/bluesky-social/indigo/api"
"github.com/bluesky-social/indigo/repo"
"github.com/bluesky-social/indigo/util"
sqlbs "github.com/ipfs/go-bs-sqlite3"
"github.com/ipfs/go-cid"
flatfs "github.com/ipfs/go-ds-flatfs"
Expand Down Expand Up @@ -110,7 +111,8 @@ func TestBasicOperation(t *testing.T) {
t.Fatal(err)
}

nroot, err := rr.Commit(ctx)
kmgr := &util.FakeKeyManager{}
nroot, err := rr.Commit(ctx, kmgr.SignForUser)
if err != nil {
t.Fatal(err)
}
Expand All @@ -132,15 +134,16 @@ func TestBasicOperation(t *testing.T) {
}

func setupRepo(ctx context.Context, bs blockstore.Blockstore) (cid.Cid, error) {
nr := repo.NewRepo(ctx, bs)
nr := repo.NewRepo(ctx, "did:foo", bs)

if _, _, err := nr.CreateRecord(ctx, "app.bsky.feed.post", &api.PostRecord{
Text: fmt.Sprintf("hey look its a tweet %s", time.Now()),
}); err != nil {
return cid.Undef, err
}

ncid, err := nr.Commit(ctx)
kmgr := &util.FakeKeyManager{}
ncid, err := nr.Commit(ctx, kmgr.SignForUser)
if err != nil {
return cid.Undef, err
}
Expand Down Expand Up @@ -190,7 +193,8 @@ func BenchmarkRepoWritesCarstore(b *testing.B) {
b.Fatal(err)
}

nroot, err := rr.Commit(ctx)
kmgr := &util.FakeKeyManager{}
nroot, err := rr.Commit(ctx, kmgr.SignForUser)
if err != nil {
b.Fatal(err)
}
Expand Down Expand Up @@ -232,7 +236,8 @@ func BenchmarkRepoWritesFlatfs(b *testing.B) {
b.Fatal(err)
}

nroot, err := rr.Commit(ctx)
kmgr := &util.FakeKeyManager{}
nroot, err := rr.Commit(ctx, kmgr.SignForUser)
if err != nil {
b.Fatal(err)
}
Expand Down Expand Up @@ -269,7 +274,8 @@ func BenchmarkRepoWritesSqlite(b *testing.B) {
b.Fatal(err)
}

nroot, err := rr.Commit(ctx)
kmgr := &util.FakeKeyManager{}
nroot, err := rr.Commit(ctx, kmgr.SignForUser)
if err != nil {
b.Fatal(err)
}
Expand Down
7 changes: 4 additions & 3 deletions cmd/bigsky/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,10 @@ func main() {
return err
}

repoman := repomgr.NewRepoManager(db, cstore)
didr := &api.PLCServer{Host: cctx.String("plc")}
kmgr := indexer.NewKeyManager(didr, nil)

repoman := repomgr.NewRepoManager(db, cstore, kmgr)

evtman := events.NewEventManager()

Expand All @@ -124,8 +127,6 @@ func main() {
// indexer just take optional callbacks for notification stuff
notifman := notifs.NewNotificationManager(db, repoman.GetRecord)

didr := &api.PLCServer{Host: cctx.String("plc")}

ix, err := indexer.NewIndexer(db, notifman, evtman, didr, repoman, true)
if err != nil {
return err
Expand Down
19 changes: 14 additions & 5 deletions cmd/gosky/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
atproto "github.com/bluesky-social/indigo/api/atproto"
bsky "github.com/bluesky-social/indigo/api/bsky"
cliutil "github.com/bluesky-social/indigo/cmd/gosky/util"
"github.com/bluesky-social/indigo/key"
"github.com/bluesky-social/indigo/repo"
"github.com/ipfs/go-cid"
"github.com/lestrrat-go/jwx/jwa"
Expand All @@ -24,6 +23,7 @@ import (
rejson "github.com/polydawn/refmt/json"
"github.com/polydawn/refmt/shared"
cli "github.com/urfave/cli/v2"
"github.com/whyrusleeping/go-did"
)

func main() {
Expand Down Expand Up @@ -202,7 +202,7 @@ var didCreateCmd = &cli.Command{
return err
}

fmt.Println("KEYDID: ", sigkey.DID())
fmt.Println("KEYDID: ", sigkey.Public().DID())

ndid, err := s.CreateDID(context.TODO(), sigkey, recoverydid, handle, service)
if err != nil {
Expand All @@ -214,7 +214,7 @@ var didCreateCmd = &cli.Command{
},
}

func loadKey(kfile string) (*key.Key, error) {
func loadKey(kfile string) (*did.PrivKey, error) {
kb, err := os.ReadFile(kfile)
if err != nil {
return nil, err
Expand All @@ -234,9 +234,18 @@ func loadKey(kfile string) (*key.Key, error) {
return nil, fmt.Errorf("need a curve set")
}

return &key.Key{
var out string
kts := string(curve.(jwa.EllipticCurveAlgorithm))
switch kts {
case "P-256":
out = did.KeyTypeP256
default:
return nil, fmt.Errorf("unrecognized key type: %s", kts)
}

return &did.PrivKey{
Raw: &spk,
Type: string(curve.(jwa.EllipticCurveAlgorithm)),
Type: out,
}, nil
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/stress/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ var genRepoCmd = &cli.Command{

ctx := context.Background()

r := repo.NewRepo(ctx, membs)
r := repo.NewRepo(ctx, "did:plc:foobar", membs)

root, err := testing.GenerateFakeRepo(r, l)
if err != nil {
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ require (
github.com/ipfs/go-log/v2 v2.5.1
github.com/ipld/go-car v0.5.0
github.com/ipld/go-car/v2 v2.5.1
github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52
github.com/labstack/echo/v4 v4.10.0
github.com/lestrrat-go/jwx v1.2.25
github.com/lestrrat-go/jwx/v2 v2.0.8
Expand All @@ -29,7 +30,7 @@ require (
github.com/stretchr/testify v1.8.1
github.com/urfave/cli/v2 v2.23.7
github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa
github.com/whyrusleeping/go-did v0.0.0-20221105001742-8d9e0ffb0d59
github.com/whyrusleeping/go-did v0.0.0-20230210051655-85c9ba6709ab
go.opentelemetry.io/otel v1.11.2
go.opentelemetry.io/otel/exporters/jaeger v1.11.2
go.opentelemetry.io/otel/sdk v1.11.2
Expand Down
14 changes: 6 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ github.com/ipfs/go-car v0.0.4 h1:zLhxykvk4SFU4oIpgcIoiolVL3jqcK0hjqcQfUSs4dk=
github.com/ipfs/go-car v0.0.4/go.mod h1:eZX0EppfsvSQN8IsJnx57bheogWMgQjJVWU/fDA7ySQ=
github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M=
github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog=
github.com/ipfs/go-cid v0.0.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I=
Expand Down Expand Up @@ -144,8 +143,6 @@ github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyB
github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8=
github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ=
github.com/ipfs/go-ipld-cbor v0.0.2/go.mod h1:wTBtrQZA3SoFKMVkp6cn6HMRteIB1VsmHA0AQFOn7Nc=
github.com/ipfs/go-ipld-cbor v0.0.6 h1:pYuWHyvSpIsOOLw4Jy7NbBkCyzLDcl64Bf/LZW7eBQ0=
github.com/ipfs/go-ipld-cbor v0.0.6/go.mod h1:ssdxxaLJPXH7OjF5V4NSjBbcfh+evoR4ukuru0oPXMA=
github.com/ipfs/go-ipld-cbor v0.0.7-0.20230126201833-a73d038d90bc h1:eUEo764smNy0EVRuMTSmirmuh552Mf2aBjfpDcLnDa8=
github.com/ipfs/go-ipld-cbor v0.0.7-0.20230126201833-a73d038d90bc/go.mod h1:X7SgEIwC4COC5OWfcepZBWafO5kA1Rmt9ZsLLbhihQk=
github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dCDnkOJhcZkms=
Expand Down Expand Up @@ -185,6 +182,8 @@ github.com/ipld/go-ipld-prime v0.9.1-0.20210324083106-dc342a9917db/go.mod h1:KvB
github.com/ipld/go-ipld-prime v0.19.0 h1:5axC7rJmPc17Emw6TelxGwnzALk0PdupZ2oj2roDj04=
github.com/ipld/go-ipld-prime v0.19.0/go.mod h1:Q9j3BaVXwaA3o5JUDNvptDDr/x8+F7FG6XJ8WI3ILg4=
github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd73 h1:TsyATB2ZRRQGTwafJdgEUQkmjOExRV0DNokcihZxbnQ=
github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c=
github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52/go.mod h1:fdg+/X9Gg4AsAIzWpEHwnqd+QY3b7lajxyjE1m4hkq4=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
Expand Down Expand Up @@ -442,14 +441,13 @@ github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvS
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 h1:5HZfQkwe0mIfyDmc1Em5GqlNRzcdtlv4HTNmdpt7XH0=
github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI=
github.com/whyrusleeping/cbor-gen v0.0.0-20230109192608-0173f1e641ac h1:vSeRURgERu0v7h+bKvlP0wuT+inofyu61R15qka/Xh0=
github.com/whyrusleeping/cbor-gen v0.0.0-20230109192608-0173f1e641ac/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa h1:EyA027ZAkuaCLoxVX4r1TZMPy1d31fM6hbfQ4OU4I5o=
github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E=
github.com/whyrusleeping/go-did v0.0.0-20221105001742-8d9e0ffb0d59 h1:dRYr/sfpZjX8evmbFrOG7ldkzdk5TLMGRVM40k1AZPQ=
github.com/whyrusleeping/go-did v0.0.0-20221105001742-8d9e0ffb0d59/go.mod h1:mX/AQ/SS9KrCwO8V+IWyIozytxw5gw75cMHymoJvMGo=
github.com/whyrusleeping/go-did v0.0.0-20230209234736-e14671c25e01 h1:YPGD8CeME7k4QgW0/lb1bR8nYSQDQbxoTPqb4zKke78=
github.com/whyrusleeping/go-did v0.0.0-20230209234736-e14671c25e01/go.mod h1:mX/AQ/SS9KrCwO8V+IWyIozytxw5gw75cMHymoJvMGo=
github.com/whyrusleeping/go-did v0.0.0-20230210051655-85c9ba6709ab h1:u1P8OjfkqR7LGZV91TMS76NEecUPa/boX29FBMNq+nw=
github.com/whyrusleeping/go-did v0.0.0-20230210051655-85c9ba6709ab/go.mod h1:qPtRyexGM5XMHFIfjH+EiA/A/1n2JakWEdMPC53pJAE=
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc=
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM=
github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f/go.mod h1:cZNvX9cFybI01GriPRMXDtczuvUhgbcYr9iCGaNlRv8=
Expand Down
62 changes: 62 additions & 0 deletions indexer/keymgr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package indexer

import (
"context"
"crypto"
"fmt"
"time"

"github.com/bluesky-social/indigo/plc"
did "github.com/whyrusleeping/go-did"
)

type KeyManager struct {
didr plc.PLCClient

signingKey *did.PrivKey
}

func NewKeyManager(didr plc.PLCClient, k *did.PrivKey) *KeyManager {
return &KeyManager{
didr: didr,
signingKey: k,
}
}

type cachedKey struct {
cachedAt time.Time
pub crypto.PublicKey
}

func (km *KeyManager) VerifyUserSignature(ctx context.Context, did string, sig []byte, msg []byte) error {
k, err := km.getKey(ctx, did)
if err != nil {
return err
}

return k.Verify(msg, sig)
}

func (km *KeyManager) getKey(ctx context.Context, did string) (*did.PubKey, error) {
// TODO: caching should be done at the DID document level, that way we can
// have a thing that subscribes to plc updates for cache busting
doc, err := km.didr.GetDocument(ctx, did)
if err != nil {
return nil, err
}

pubk, err := doc.GetPublicKey("#signingKey")
if err != nil {
return nil, err
}

return pubk, nil
}

func (km *KeyManager) SignForUser(ctx context.Context, did string, msg []byte) ([]byte, error) {
if km.signingKey == nil {
return nil, fmt.Errorf("key manager does not have a signing key, cannot sign")
}

return km.signingKey.Sign(msg)
}
2 changes: 1 addition & 1 deletion indexer/posts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func testIndexer(t *testing.T) *testIx {
t.Fatal(err)
}

repoman := repomgr.NewRepoManager(maindb, cs)
repoman := repomgr.NewRepoManager(maindb, cs, &util.FakeKeyManager{})
notifman := notifs.NewNotificationManager(maindb, repoman.GetRecord)
evtman := events.NewEventManager()

Expand Down
Loading

0 comments on commit ab83a33

Please sign in to comment.