github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/namesys/routing.go (about) 1 package namesys 2 3 import ( 4 "fmt" 5 6 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" 7 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto" 8 9 mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash" 10 ci "github.com/jbenet/go-ipfs/crypto" 11 pb "github.com/jbenet/go-ipfs/namesys/internal/pb" 12 routing "github.com/jbenet/go-ipfs/routing" 13 u "github.com/jbenet/go-ipfs/util" 14 ) 15 16 var log = u.Logger("namesys") 17 18 // routingResolver implements NSResolver for the main IPFS SFS-like naming 19 type routingResolver struct { 20 routing routing.IpfsRouting 21 } 22 23 // NewRoutingResolver constructs a name resolver using the IPFS Routing system 24 // to implement SFS-like naming on top. 25 func NewRoutingResolver(route routing.IpfsRouting) Resolver { 26 return &routingResolver{routing: route} 27 } 28 29 // CanResolve implements Resolver. Checks whether name is a b58 encoded string. 30 func (r *routingResolver) CanResolve(name string) bool { 31 _, err := mh.FromB58String(name) 32 return err == nil 33 } 34 35 // Resolve implements Resolver. Uses the IPFS routing system to resolve SFS-like 36 // names. 37 func (r *routingResolver) Resolve(name string) (string, error) { 38 log.Debugf("RoutingResolve: '%s'", name) 39 ctx := context.TODO() 40 hash, err := mh.FromB58String(name) 41 if err != nil { 42 log.Warning("RoutingResolve: bad input hash: [%s]\n", name) 43 return "", err 44 } 45 // name should be a multihash. if it isn't, error out here. 46 47 // use the routing system to get the name. 48 // /ipns/<name> 49 h := u.Hash([]byte("/ipns/" + name)) 50 51 ipnsKey := u.Key(h) 52 val, err := r.routing.GetValue(ctx, ipnsKey) 53 if err != nil { 54 log.Warning("RoutingResolve get failed.") 55 return "", err 56 } 57 58 entry := new(pb.IpnsEntry) 59 err = proto.Unmarshal(val, entry) 60 if err != nil { 61 return "", err 62 } 63 64 // name should be a public key retrievable from ipfs 65 // /ipfs/<name> 66 key := u.Key(hash) 67 pkval, err := r.routing.GetValue(ctx, key) 68 if err != nil { 69 log.Warning("RoutingResolve PubKey Get failed.") 70 return "", err 71 } 72 73 // get PublicKey from node.Data 74 pk, err := ci.UnmarshalPublicKey(pkval) 75 if err != nil { 76 return "", err 77 } 78 79 // check sig with pk 80 if ok, err := pk.Verify(entry.GetValue(), entry.GetSignature()); err != nil || !ok { 81 return "", fmt.Errorf("Invalid value. Not signed by PrivateKey corresponding to %v", pk) 82 } 83 84 // ok sig checks out. this is a valid name. 85 return string(entry.GetValue()), nil 86 }