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  }