// getLocal attempts to retrieve the value from the datastore func (dht *IpfsDHT) getLocal(key u.Key) ([]byte, error) { dht.dslock.Lock() defer dht.dslock.Unlock() log.Debug("getLocal %s", key) v, err := dht.datastore.Get(key.DsKey()) if err != nil { return nil, err } log.Debug("found in db") byt, ok := v.([]byte) if !ok { return nil, errors.New("value stored in datastore not []byte") } rec := new(pb.Record) err = proto.Unmarshal(byt, rec) if err != nil { return nil, err } // TODO: 'if paranoid' if u.Debug { err = dht.verifyRecord(rec) if err != nil { log.Errorf("local record verify failed: %s", err) return nil, err } } return rec.GetValue(), nil }
// creates and signs a dht record for the given key/value pair func (dht *IpfsDHT) makePutRecord(key u.Key, value []byte) (*pb.Record, error) { record := new(pb.Record) record.Key = proto.String(string(key)) record.Value = value record.Author = proto.String(string(dht.self.ID())) blob := bytes.Join([][]byte{[]byte(key), value, []byte(dht.self.ID())}, []byte{}) sig, err := dht.self.PrivKey().Sign(blob) if err != nil { return nil, err } record.Signature = sig return record, nil }
func (dht *IpfsDHT) verifyRecord(r *pb.Record) error { // First, validate the signature p, err := dht.peerstore.Get(peer.ID(r.GetAuthor())) if err != nil { return err } k := u.Key(r.GetKey()) blob := bytes.Join([][]byte{[]byte(k), r.GetValue(), []byte(r.GetAuthor())}, []byte{}) ok, err := p.PubKey().Verify(blob, r.GetSignature()) if err != nil { log.Error("Signature verify failed.") return err } if !ok { return ErrBadRecord } // Now, check validity func parts := strings.Split(r.GetKey(), "/") if len(parts) < 3 { log.Errorf("Record had bad key: %s", u.Key(r.GetKey())) return ErrBadRecord } fnc, ok := dht.Validators[parts[1]] if !ok { log.Errorf("Unrecognized key prefix: %s", parts[1]) return ErrInvalidRecordType } return fnc(u.Key(r.GetKey()), r.GetValue()) }