// resolveOnce implements resolver. Uses the IPFS routing system to // resolve SFS-like names. func (r *routingResolver) resolveOnce(ctx context.Context, name string) (path.Path, error) { log.Debugf("RoutingResolve: '%s'", name) hash, err := mh.FromB58String(name) if err != nil { log.Warning("RoutingResolve: bad input hash: [%s]\n", name) return "", err } // name should be a multihash. if it isn't, error out here. // use the routing system to get the name. // /ipns/<name> h := []byte("/ipns/" + string(hash)) ipnsKey := key.Key(h) val, err := r.routing.GetValue(ctx, ipnsKey) if err != nil { log.Warning("RoutingResolve get failed.") return "", err } entry := new(pb.IpnsEntry) err = proto.Unmarshal(val, entry) if err != nil { return "", err } // name should be a public key retrievable from ipfs pubkey, err := routing.GetPublicKey(r.routing, ctx, hash) if err != nil { return "", err } hsh, _ := pubkey.Hash() log.Debugf("pk hash = %s", key.Key(hsh)) // check sig with pk if ok, err := pubkey.Verify(ipnsEntryDataForSig(entry), entry.GetSignature()); err != nil || !ok { return "", fmt.Errorf("Invalid value. Not signed by PrivateKey corresponding to %v", pubkey) } // ok sig checks out. this is a valid name. // check for old style record: valh, err := mh.Cast(entry.GetValue()) if err != nil { // Not a multihash, probably a new record return path.ParsePath(string(entry.GetValue())) } else { // Its an old style multihash record log.Warning("Detected old style multihash record") return path.FromKey(key.Key(valh)), nil } }