@cryptotaxi247 / kubo / commits / f21ec1923

verify ipns records

Jeromy committed Nov 11, 2014 at 17:58 UTC f21ec1923a7ea2ffeb82a87f6f08324adacb9f7b
7 files changed +111 -13
core/core.go
+2
@@ -156,6 +156,8 @@ func NewIpfsNode(cfg *config.Config, online bool) (n *IpfsNode, err error) {
156
157 // setup routing service
158 dhtRouting := dht.NewDHT(ctx, n.Identity, n.Peerstore, n.Network, dhtService, n.Datastore)
159 + dhtRouting.Validators["ipns"] = namesys.ValidateIpnsRecord
160 +
161 // TODO(brian): perform this inside NewDHT factory method
162 dhtService.SetHandler(dhtRouting) // wire the handler to the service.
163 n.Routing = dhtRouting
namesys/internal/pb/namesys.pb.go
+52 -4
@@ -13,17 +13,50 @@ It has these top-level messages:
13 */
14 package namesys_pb
15
16 -import proto "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/gogoprotobuf/proto"
16 +import proto "code.google.com/p/gogoprotobuf/proto"
17 import math "math"
18
19 // Reference imports to suppress errors if they are not otherwise used.
20 var _ = proto.Marshal
21 var _ = math.Inf
22
23 +type IpnsEntry_ValidityType int32
24 +
25 +const (
26 + // setting an EOL says "this record is valid until..."
27 + IpnsEntry_EOL IpnsEntry_ValidityType = 0
28 +)
29 +
30 +var IpnsEntry_ValidityType_name = map[int32]string{
31 + 0: "EOL",
32 +}
33 +var IpnsEntry_ValidityType_value = map[string]int32{
34 + "EOL": 0,
35 +}
36 +
37 +func (x IpnsEntry_ValidityType) Enum() *IpnsEntry_ValidityType {
38 + p := new(IpnsEntry_ValidityType)
39 + *p = x
40 + return p
41 +}
42 +func (x IpnsEntry_ValidityType) String() string {
43 + return proto.EnumName(IpnsEntry_ValidityType_name, int32(x))
44 +}
45 +func (x *IpnsEntry_ValidityType) UnmarshalJSON(data []byte) error {
46 + value, err := proto.UnmarshalJSONEnum(IpnsEntry_ValidityType_value, data, "IpnsEntry_ValidityType")
47 + if err != nil {
48 + return err
49 + }
50 + *x = IpnsEntry_ValidityType(value)
51 + return nil
52 +}
53 +
54 type IpnsEntry struct {
24 - Value []byte `protobuf:"bytes,1,req,name=value" json:"value,omitempty"`
25 - Signature []byte `protobuf:"bytes,2,req,name=signature" json:"signature,omitempty"`
26 - XXX_unrecognized []byte `json:"-"`
55 + Value []byte `protobuf:"bytes,1,req,name=value" json:"value,omitempty"`
56 + Signature []byte `protobuf:"bytes,2,req,name=signature" json:"signature,omitempty"`
57 + ValidityType *IpnsEntry_ValidityType `protobuf:"varint,3,opt,name=validityType,enum=namesys.pb.IpnsEntry_ValidityType" json:"validityType,omitempty"`
58 + Validity []byte `protobuf:"bytes,4,opt,name=validity" json:"validity,omitempty"`
59 + XXX_unrecognized []byte `json:"-"`
60 }
61
62 func (m *IpnsEntry) Reset() { *m = IpnsEntry{} }
@@ -44,5 +77,20 @@ func (m *IpnsEntry) GetSignature() []byte {
77 return nil
78 }
79
80 +func (m *IpnsEntry) GetValidityType() IpnsEntry_ValidityType {
81 + if m != nil && m.ValidityType != nil {
82 + return *m.ValidityType
83 + }
84 + return IpnsEntry_EOL
85 +}
86 +
87 +func (m *IpnsEntry) GetValidity() []byte {
88 + if m != nil {
89 + return m.Validity
90 + }
91 + return nil
92 +}
93 +
94 func init() {
95 + proto.RegisterEnum("namesys.pb.IpnsEntry_ValidityType", IpnsEntry_ValidityType_name, IpnsEntry_ValidityType_value)
96 }
namesys/internal/pb/namesys.proto
+7
@@ -1,6 +1,13 @@
1 package namesys.pb;
2
3 message IpnsEntry {
4 + enum ValidityType {
5 + // setting an EOL says "this record is valid until..."
6 + EOL = 0;
7 + }
8 required bytes value = 1;
9 required bytes signature = 2;
10 +
11 + optional ValidityType validityType = 3;
12 + optional bytes validity = 4;
13 }
namesys/publisher.go
+47 -2
@@ -1,6 +1,8 @@
1 package namesys
2
3 import (
4 + "bytes"
5 + "errors"
6 "fmt"
7 "time"
8
@@ -14,6 +16,12 @@ import (
16 u "github.com/jbenet/go-ipfs/util"
17 )
18
19 +// ErrExpiredRecord should be returned when an ipns record is
20 +// invalid due to being too old
21 +var ErrExpiredRecord = errors.New("expired record")
22 +
23 +var ErrUnrecognizedValidity = errors.New("unrecognized validity type")
24 +
25 // ipnsPublisher is capable of publishing and resolving names to the IPFS
26 // routing system.
27 type ipnsPublisher struct {
@@ -76,11 +84,48 @@ func (p *ipnsPublisher) Publish(k ci.PrivKey, value string) error {
84
85 func createRoutingEntryData(pk ci.PrivKey, val string) ([]byte, error) {
86 entry := new(pb.IpnsEntry)
79 - sig, err := pk.Sign([]byte(val))
87 +
88 + entry.Value = []byte(val)
89 + typ := pb.IpnsEntry_EOL
90 + entry.ValidityType = &typ
91 + entry.Validity = []byte(time.Now().Add(time.Hour * 24).String())
92 +
93 + sig, err := pk.Sign(ipnsEntryDataForSig(entry))
94 if err != nil {
95 return nil, err
96 }
97 entry.Signature = sig
84 - entry.Value = []byte(val)
98 return proto.Marshal(entry)
99 }
100 +
101 +func ipnsEntryDataForSig(e *pb.IpnsEntry) []byte {
102 + return bytes.Join([][]byte{
103 + e.Value,
104 + e.Validity,
105 + []byte(fmt.Sprint(e.GetValidityType())),
106 + },
107 + []byte{})
108 +}
109 +
110 +func ValidateIpnsRecord(k u.Key, val []byte) error {
111 + entry := new(pb.IpnsEntry)
112 + err := proto.Unmarshal(val, entry)
113 + if err != nil {
114 + return err
115 + }
116 + switch entry.GetValidityType() {
117 + case pb.IpnsEntry_EOL:
118 + defaultTimeFormat := "2006-01-02 15:04:05.999999999 -0700 MST"
119 + t, err := time.Parse(defaultTimeFormat, string(entry.GetValue()))
120 + if err != nil {
121 + log.Error("Failed parsing time for ipns record EOL")
122 + return err
123 + }
124 + if time.Now().After(t) {
125 + return ErrExpiredRecord
126 + }
127 + default:
128 + return ErrUnrecognizedValidity
129 + }
130 + return nil
131 +}
namesys/routing.go
+3 -1
@@ -75,9 +75,11 @@ func (r *routingResolver) Resolve(name string) (string, error) {
75 if err != nil {
76 return "", err
77 }
78 + hsh, _ := pk.Hash()
79 + log.Debugf("pk hash = %s", u.Key(hsh))
80
81 // check sig with pk
80 - if ok, err := pk.Verify(entry.GetValue(), entry.GetSignature()); err != nil || !ok {
82 + if ok, err := pk.Verify(ipnsEntryDataForSig(entry), entry.GetSignature()); err != nil || !ok {
83 return "", fmt.Errorf("Invalid value. Not signed by PrivateKey corresponding to %v", pk)
84 }
85
routing/dht/dht.go
-1
@@ -86,7 +86,6 @@ func NewDHT(ctx context.Context, p peer.Peer, ps peer.Peerstore, dialer inet.Dia
86 dht.birth = time.Now()
87
88 dht.Validators = make(map[string]ValidatorFunc)
89 - dht.Validators["ipns"] = ValidateIpnsRecord
89 dht.Validators["pk"] = ValidatePublicKeyRecord
90
91 if doPinging {
routing/dht/records.go
-5
@@ -96,11 +96,6 @@ func (dht *IpfsDHT) verifyRecord(r *pb.Record) error {
96 return fnc(u.Key(r.GetKey()), r.GetValue())
97 }
98
99 -func ValidateIpnsRecord(k u.Key, val []byte) error {
100 - // TODO:
101 - return nil
102 -}
103 -
99 func ValidatePublicKeyRecord(k u.Key, val []byte) error {
100 keyparts := bytes.Split([]byte(k), []byte("/"))
101 if len(keyparts) < 3 {