github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/routing/record/validation.go (about) 1 package record 2 3 import ( 4 "bytes" 5 "errors" 6 "strings" 7 8 key "github.com/ipfs/go-ipfs/blocks/key" 9 ci "github.com/ipfs/go-ipfs/p2p/crypto" 10 pb "github.com/ipfs/go-ipfs/routing/dht/pb" 11 u "github.com/ipfs/go-ipfs/util" 12 ) 13 14 // ValidatorFunc is a function that is called to validate a given 15 // type of DHTRecord. 16 type ValidatorFunc func(key.Key, []byte) error 17 18 // ErrBadRecord is returned any time a dht record is found to be 19 // incorrectly formatted or signed. 20 var ErrBadRecord = errors.New("bad dht record") 21 22 // ErrInvalidRecordType is returned if a DHTRecord keys prefix 23 // is not found in the Validator map of the DHT. 24 var ErrInvalidRecordType = errors.New("invalid record keytype") 25 26 // Validator is an object that helps ensure routing records are valid. 27 // It is a collection of validator functions, each of which implements 28 // its own notion of validity. 29 type Validator map[string]*ValidChecker 30 31 type ValidChecker struct { 32 Func ValidatorFunc 33 Sign bool 34 } 35 36 // VerifyRecord checks a record and ensures it is still valid. 37 // It runs needed validators 38 func (v Validator) VerifyRecord(r *pb.Record) error { 39 // Now, check validity func 40 parts := strings.Split(r.GetKey(), "/") 41 if len(parts) < 3 { 42 log.Infof("Record key does not have validator: %s", key.Key(r.GetKey())) 43 return nil 44 } 45 46 val, ok := v[parts[1]] 47 if !ok { 48 log.Infof("Unrecognized key prefix: %s", parts[1]) 49 return ErrInvalidRecordType 50 } 51 52 return val.Func(key.Key(r.GetKey()), r.GetValue()) 53 } 54 55 func (v Validator) IsSigned(k key.Key) (bool, error) { 56 // Now, check validity func 57 parts := strings.Split(string(k), "/") 58 if len(parts) < 3 { 59 log.Infof("Record key does not have validator: %s", k) 60 return false, nil 61 } 62 63 val, ok := v[parts[1]] 64 if !ok { 65 log.Infof("Unrecognized key prefix: %s", parts[1]) 66 return false, ErrInvalidRecordType 67 } 68 69 return val.Sign, nil 70 } 71 72 // ValidatePublicKeyRecord implements ValidatorFunc and 73 // verifies that the passed in record value is the PublicKey 74 // that matches the passed in key. 75 func ValidatePublicKeyRecord(k key.Key, val []byte) error { 76 keyparts := bytes.Split([]byte(k), []byte("/")) 77 if len(keyparts) < 3 { 78 return errors.New("invalid key") 79 } 80 81 pkh := u.Hash(val) 82 if !bytes.Equal(keyparts[2], pkh) { 83 return errors.New("public key does not match storage key") 84 } 85 return nil 86 } 87 88 var PublicKeyValidator = &ValidChecker{ 89 Func: ValidatePublicKeyRecord, 90 Sign: false, 91 } 92 93 func CheckRecordSig(r *pb.Record, pk ci.PubKey) error { 94 blob := RecordBlobForSig(r) 95 good, err := pk.Verify(blob, r.Signature) 96 if err != nil { 97 return nil 98 } 99 if !good { 100 return errors.New("invalid record signature") 101 } 102 return nil 103 }