Skip to content

Commit

Permalink
passing tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tobowers committed Jun 7, 2020
1 parent 1e0fbde commit 9b9d035
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 19 deletions.
35 changes: 27 additions & 8 deletions aggregator/api/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/graph-gophers/graphql-go"
"github.com/graph-gophers/graphql-go/relay"
"github.com/quorumcontrol/chaintree/graftabledag"
"github.com/quorumcontrol/tupelo-lite/aggregator"
"github.com/quorumcontrol/tupelo-lite/aggregator/api"
"github.com/quorumcontrol/tupelo-lite/aggregator/identity"
Expand All @@ -30,18 +31,26 @@ func CorsMiddleware(next http.Handler) http.Handler {
})
}

func IdentityMiddleware(next http.Handler) http.Handler {
func IdentityMiddleware(next http.Handler, getter graftabledag.DagGetter) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
id, err := identity.FromHeader(r.Header)
if err != nil {
w.WriteHeader(500)
return
}
logger.Debugf("id: %v", id)
if id != nil {
newR := r.WithContext(context.WithValue(r.Context(), api.IdentityContextKey, id.Identity))
next.ServeHTTP(w, newR)
return
isVerified, err := id.Verify(context.TODO(), getter)
if err != nil {
logger.Errorf("error verifying: %v", err)
w.WriteHeader(500)
return
}
if isVerified {
logger.Debugf("id: %v", id)
newR := r.WithContext(context.WithValue(r.Context(), api.IdentityContextKey, id.Identity))
next.ServeHTTP(w, newR)
return
}
}
next.ServeHTTP(w, r)
})
Expand All @@ -53,7 +62,17 @@ func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

r, err := api.NewResolver(ctx, &api.Config{KeyValueStore: aggregator.NewMemoryStore()})
// TODO: publish this to an mqtt broker
updateChan := make(aggregator.UpdateChan, 10)
go func() {
for {
// up := <-updateChan
// logger.Debugf("updated: %v", up)
<-updateChan
}
}()

r, err := api.NewResolver(ctx, &api.Config{KeyValueStore: aggregator.NewMemoryStore(), UpdateChannel: updateChan})
if err != nil {
panic(err)
}
Expand All @@ -64,9 +83,9 @@ func main() {
http.Handle("/", CorsMiddleware(IdentityMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Printf("rendering igraphql")
w.Write(page)
}))))
}), r.Aggregator)))

http.Handle("/graphql", CorsMiddleware(IdentityMiddleware((&relay.Handler{Schema: schema}))))
http.Handle("/graphql", CorsMiddleware(IdentityMiddleware(&relay.Handler{Schema: schema}, r.Aggregator)))

fmt.Println("running on port 9011 path: /graphql")
log.Fatal(http.ListenAndServe(":9011", nil))
Expand Down
1 change: 1 addition & 0 deletions aggregator/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.14
require (
github.com/aws/aws-lambda-go v1.17.0
github.com/aws/aws-sdk-go v1.31.12
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
github.com/ethereum/go-ethereum v1.9.3
github.com/graph-gophers/graphql-go v0.0.0-20200309224638-dae41bde9ef9
github.com/ipfs/go-cid v0.0.5
Expand Down
21 changes: 18 additions & 3 deletions aggregator/identity/identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import (
"fmt"
"time"

"github.com/davecgh/go-spew/spew"
logging "github.com/ipfs/go-log"

"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
cbornode "github.com/ipfs/go-ipld-cbor"
format "github.com/ipfs/go-ipld-format"
Expand All @@ -20,7 +22,7 @@ import (

var logger = logging.Logger("identity")

const IdentityHeaderField = "x-tupelo-id"
const IdentityHeaderField = "X-Tupelo-Id"

func init() {
cbornode.RegisterCborType(Identity{})
Expand Down Expand Up @@ -73,48 +75,61 @@ func (i *Identity) Sign(key *ecdsa.PrivateKey) (*IdentityWithSignature, error) {
}

func (is *IdentityWithSignature) Verify(ctx context.Context, getter graftabledag.DagGetter) (bool, error) {
logger.Debugf("Verifying identity: %s", spew.Sdump(is.Identity))
sw := &safewrap.SafeWrap{}
wrapped := sw.WrapObject(is.Identity)
if sw.Err != nil {
return false, fmt.Errorf("error wrapping: %w", sw.Err)
}
recoveredPub, err := crypto.SigToPub(nodeToHash(wrapped), is.Signature)

hsh := nodeToHash(wrapped)
logger.Debugf("verifying %s", hexutil.Encode(hsh))

recoveredPub, err := crypto.SigToPub(hsh, is.Signature)
if err != nil {
return false, fmt.Errorf("error recovering signature: %w", err)
}

verified := crypto.VerifySignature(crypto.FromECDSAPub(recoveredPub), nodeToHash(wrapped), is.Signature[:len(is.Signature)-1])
verified := crypto.VerifySignature(crypto.FromECDSAPub(recoveredPub), hsh, is.Signature[:len(is.Signature)-1])
if !verified {
logger.Warningf("unverified signature")
return false, nil
}

now := time.Now().UTC().Unix()

if now > is.Identity.Exp {
logger.Warningf("expired identity: now %d, exp: %d", now, is.Identity.Exp)
return false, nil
}
latest, err := getter.GetLatest(ctx, is.Sub)
if err != nil {
logger.Errorf("error getting latest: %v", err)
return false, fmt.Errorf("error getting latest: %w", err)
}
graftedOwnership, err := types.NewGraftedOwnership(latest.Dag, getter)
if err != nil {
logger.Errorf("error getting ownership: %v", err)
return false, fmt.Errorf("error getting ownership: %w", err)
}

addrs, err := graftedOwnership.ResolveOwners(ctx)
if err != nil {
logger.Errorf("error resolving owners: %v", err)
return false, fmt.Errorf("error resolving owners: %w", err)
}
identityAddr, err := is.Address()
if err != nil {
logger.Errorf("error getting addr: %v", err)
return false, fmt.Errorf("error getting addr: %w", err)
}
logger.Debugf("addrs: %v, identity Addr: %s", addrs, identityAddr)
for _, addr := range addrs {
if addr == identityAddr {
return true, nil
}
}
logger.Debugf("no addr found")
return false, nil
}

Expand Down
12 changes: 7 additions & 5 deletions src/client.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,18 +82,20 @@ describe("Client", () => {
repo.close()
})

it('identifies', async () => {
it('identifies without a policy', async () => {
let cli = new Client("http://localhost:9011/graphql")

const repo = await Repo.memoryRepo("identifies")

const tree = await ChainTree.createRandom(new IpfsBlockService(repo.repo))
const abr = await tree.newAddBlockRequest([setDataTransaction("hi", "hi")])

cli.identify((await tree.id())!, tree.key!)

const resp = await cli.addBlock(abr)
expect(resp.errors).to.be.undefined
const did = (await tree.id())
cli.identify(did!, tree.key!)
const resolveResp = await cli.resolve(did!, "/tree/data/hi")
expect(resolveResp.value).to.equal("hi")

repo.close()
})

Expand Down Expand Up @@ -134,7 +136,7 @@ describe("Client", () => {
const badKey = EcdsaKey.generate()
cli.identify((await tree.id())!, badKey)
const queryResp2 = await cli.resolve((await tree.id())!, "tree/data/locked")
expect(queryResp2.value).to.equal("worked")
expect(queryResp2.value).to.equal(null)

// however if we identify then it should actually resolve
cli.identify((await tree.id())!, tree.key!)
Expand Down
7 changes: 4 additions & 3 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const dagCBOR = require('ipld-dag-cbor');
const Block = require('ipld-block');
const log = debug("client")

const identityHeaderField = "x-tupelo-id"
const identityHeaderField = "X-Tupelo-Id"

export interface IGraphqlBlock {
data: string
Expand Down Expand Up @@ -106,6 +106,7 @@ export class Client {
iss:did,
sub: did,
iat: now.getTime() + (now.getTimezoneOffset() * 60000),
aud: "",
}
this.key = key
}
Expand All @@ -117,9 +118,9 @@ export class Client {
const now = new Date()

const identity = {...this.identity, exp: now.getTime() + (now.getTimezoneOffset() * 60000) + 10000}

log("identity: ", identity)
const sigResp = await this.key.signObject(identity)
return {...this.identity, signature: sigResp.signature}
return {...identity, signature: sigResp.signature}
}

private async identityHeaderString():Promise<undefined|string> {
Expand Down
4 changes: 4 additions & 0 deletions src/ecdsa.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { randomBytes, SigningKey, computeAddress, joinSignature } from 'ethers/utils'
import scrypt from 'scrypt-async-modern'
import pbkdf2 from 'pbkdf2'
import debug from 'debug';

const log = debug("ecdsa")

const dagCBOR = require('ipld-dag-cbor')

Expand Down Expand Up @@ -103,6 +106,7 @@ export class EcdsaKey {
const bits = dagCBOR.util.serialize(obj)

const digest = (await dagCBOR.util.cid(bits)).multihash.slice(2)
log("signing digest: ", Buffer.from(digest).toString('hex'))
let signature = signingKey.signDigest(digest);

// this is weird, but for some reason Go and JS differ in how they handle the last byte of the signature
Expand Down

0 comments on commit 9b9d035

Please sign in to comment.