mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-24 11:57:44 +08:00
embed public keys inside ipns records, use for validation
License: MIT Signed-off-by: Jeromy <jeromyj@gmail.com>
This commit is contained in:
parent
f7a980926b
commit
bc129ac5c7
@ -1,12 +1,12 @@
|
||||
// Code generated by protoc-gen-gogo.
|
||||
// source: namesys.proto
|
||||
// source: namesys/pb/namesys.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package namesys_pb is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
namesys.proto
|
||||
namesys/pb/namesys.proto
|
||||
|
||||
It has these top-level messages:
|
||||
IpnsEntry
|
||||
@ -14,10 +14,12 @@ It has these top-level messages:
|
||||
package namesys_pb
|
||||
|
||||
import proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
type IpnsEntry_ValidityType int32
|
||||
@ -52,13 +54,18 @@ func (x *IpnsEntry_ValidityType) UnmarshalJSON(data []byte) error {
|
||||
}
|
||||
|
||||
type IpnsEntry struct {
|
||||
Value []byte `protobuf:"bytes,1,req,name=value" json:"value,omitempty"`
|
||||
Signature []byte `protobuf:"bytes,2,req,name=signature" json:"signature,omitempty"`
|
||||
ValidityType *IpnsEntry_ValidityType `protobuf:"varint,3,opt,name=validityType,enum=namesys.pb.IpnsEntry_ValidityType" json:"validityType,omitempty"`
|
||||
Validity []byte `protobuf:"bytes,4,opt,name=validity" json:"validity,omitempty"`
|
||||
Sequence *uint64 `protobuf:"varint,5,opt,name=sequence" json:"sequence,omitempty"`
|
||||
Ttl *uint64 `protobuf:"varint,6,opt,name=ttl" json:"ttl,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Value []byte `protobuf:"bytes,1,req,name=value" json:"value,omitempty"`
|
||||
Signature []byte `protobuf:"bytes,2,req,name=signature" json:"signature,omitempty"`
|
||||
ValidityType *IpnsEntry_ValidityType `protobuf:"varint,3,opt,name=validityType,enum=namesys.pb.IpnsEntry_ValidityType" json:"validityType,omitempty"`
|
||||
Validity []byte `protobuf:"bytes,4,opt,name=validity" json:"validity,omitempty"`
|
||||
Sequence *uint64 `protobuf:"varint,5,opt,name=sequence" json:"sequence,omitempty"`
|
||||
Ttl *uint64 `protobuf:"varint,6,opt,name=ttl" json:"ttl,omitempty"`
|
||||
// in order for nodes to properly validate a record upon receipt, they need the public
|
||||
// key associated with it. For old RSA keys, its easiest if we just send this as part of
|
||||
// the record itself. For newer ed25519 keys, the public key can be embedded in the
|
||||
// peerID, making this field unnecessary.
|
||||
PubKey []byte `protobuf:"bytes,7,opt,name=pubKey" json:"pubKey,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *IpnsEntry) Reset() { *m = IpnsEntry{} }
|
||||
@ -107,6 +114,14 @@ func (m *IpnsEntry) GetTtl() uint64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *IpnsEntry) GetPubKey() []byte {
|
||||
if m != nil {
|
||||
return m.PubKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*IpnsEntry)(nil), "namesys.pb.IpnsEntry")
|
||||
proto.RegisterEnum("namesys.pb.IpnsEntry_ValidityType", IpnsEntry_ValidityType_name, IpnsEntry_ValidityType_value)
|
||||
}
|
||||
|
||||
@ -14,4 +14,10 @@ message IpnsEntry {
|
||||
optional uint64 sequence = 5;
|
||||
|
||||
optional uint64 ttl = 6;
|
||||
|
||||
// in order for nodes to properly validate a record upon receipt, they need the public
|
||||
// key associated with it. For old RSA keys, its easiest if we just send this as part of
|
||||
// the record itself. For newer ed25519 keys, the public key can be embedded in the
|
||||
// peerID, making this field unnecessary.
|
||||
optional bytes pubKey = 7;
|
||||
}
|
||||
|
||||
@ -240,6 +240,17 @@ func PutRecordToRouting(ctx context.Context, r routing.ValueStore, k ci.PubKey,
|
||||
return err
|
||||
}
|
||||
|
||||
// if we can't derive the public key from the peerID, embed the entire pubkey in
|
||||
// the record to make the verifiers job easier
|
||||
if extractedPublicKey == nil {
|
||||
pubkeyBytes, err := k.Bytes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
entry.PubKey = pubkeyBytes
|
||||
}
|
||||
|
||||
namekey, ipnskey := IpnsKeysForID(id)
|
||||
|
||||
go func() {
|
||||
@ -247,6 +258,8 @@ func PutRecordToRouting(ctx context.Context, r routing.ValueStore, k ci.PubKey,
|
||||
}()
|
||||
|
||||
// Publish the public key if a public key cannot be extracted from the ID
|
||||
// TODO: once v0.4.16 is widespread enough, we can stop doing this
|
||||
// and at that point we can even deprecate the /pk/ namespace in the dht
|
||||
if extractedPublicKey == nil {
|
||||
go func() {
|
||||
errs <- PublishPublicKey(ctx, r, namekey, k)
|
||||
|
||||
@ -3,11 +3,13 @@ package namesys
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
pb "github.com/ipfs/go-ipfs/namesys/pb"
|
||||
peer "gx/ipfs/QmcJukH2sAFjY3HdBKq35WDzWoL3UUu2gt9wdfqZTUyM74/go-libp2p-peer"
|
||||
pstore "gx/ipfs/QmdeiKhUy1TVGBaKxt7y1QmBDLBdisSrLJ1x58Eoj4PXUh/go-libp2p-peerstore"
|
||||
ic "gx/ipfs/Qme1knMqwt1hKZbc1BmQFmnm9f36nyQGwXxPGVpVJ9rMK5/go-libp2p-crypto"
|
||||
|
||||
u "gx/ipfs/QmNiJuT8Ja3hMVpBHXv3Q6dwmperaQ6JjLtpMQgMCD7xvx/go-ipfs-util"
|
||||
record "gx/ipfs/QmTUyK82BVPA6LmSzEJpfEunk9uBaQzWtMsNP917tVj4sT/go-libp2p-record"
|
||||
@ -65,10 +67,10 @@ func (v IpnsValidator) Validate(key string, value []byte) error {
|
||||
log.Debugf("failed to parse ipns record key %s into peer ID", pidString)
|
||||
return ErrKeyFormat
|
||||
}
|
||||
pubk := v.KeyBook.PubKey(pid)
|
||||
if pubk == nil {
|
||||
log.Debugf("public key with hash %s not found in peer store", pid)
|
||||
return ErrPublicKeyNotFound
|
||||
|
||||
pubk, err := v.getPublicKey(pid, entry)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting public key failed: %s", err)
|
||||
}
|
||||
|
||||
// Check the ipns record signature with the public key
|
||||
@ -94,6 +96,34 @@ func (v IpnsValidator) Validate(key string, value []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v IpnsValidator) getPublicKey(pid peer.ID, entry *pb.IpnsEntry) (ic.PubKey, error) {
|
||||
if entry.PubKey != nil {
|
||||
pk, err := ic.UnmarshalPublicKey(entry.PubKey)
|
||||
if err != nil {
|
||||
// TODO: i think this counts as a 'malformed record' and should be discarded
|
||||
log.Debugf("public key in ipns record failed to parse: ", err)
|
||||
return nil, err
|
||||
}
|
||||
expPid, err := peer.IDFromPublicKey(pk)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not regenerate peerID from pubkey: %s", err)
|
||||
}
|
||||
|
||||
if pid != expPid {
|
||||
return nil, fmt.Errorf("pubkey in record did not match expected pubkey")
|
||||
}
|
||||
|
||||
return pk, nil
|
||||
}
|
||||
|
||||
pubk := v.KeyBook.PubKey(pid)
|
||||
if pubk == nil {
|
||||
log.Debugf("public key with hash %s not found in peer store", pid)
|
||||
return nil, ErrPublicKeyNotFound
|
||||
}
|
||||
return pubk, nil
|
||||
}
|
||||
|
||||
// IpnsSelectorFunc selects the best record by checking which has the highest
|
||||
// sequence number and latest EOL
|
||||
func (v IpnsValidator) Select(k string, vals [][]byte) (int, error) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user