func ipnsEntryDataForSig(e *pb.IpnsEntry) []byte { return bytes.Join([][]byte{ e.Value, e.Validity, []byte(fmt.Sprint(e.GetValidityType())), }, []byte{}) }
func createRoutingEntryData(pk ci.PrivKey, val path.Path) ([]byte, error) { entry := new(pb.IpnsEntry) entry.Value = []byte(val) typ := pb.IpnsEntry_EOL entry.ValidityType = &typ entry.Validity = []byte(u.FormatRFC3339(time.Now().Add(time.Hour * 24))) sig, err := pk.Sign(ipnsEntryDataForSig(entry)) if err != nil { return nil, err } entry.Signature = sig return proto.Marshal(entry) }
// ValidateIpnsRecord implements ValidatorFunc and verifies that the // given 'val' is an IpnsEntry and that that entry is valid. func ValidateIpnsRecord(k key.Key, val []byte) error { entry := new(pb.IpnsEntry) err := proto.Unmarshal(val, entry) if err != nil { return err } switch entry.GetValidityType() { case pb.IpnsEntry_EOL: t, err := u.ParseRFC3339(string(entry.GetValidity())) if err != nil { log.Debug("Failed parsing time for ipns record EOL") return err } if time.Now().After(t) { return ErrExpiredRecord } default: return ErrUnrecognizedValidity } return nil }
// 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 } }