aboutsummaryrefslogtreecommitdiff
path: root/src/gnunet/core/peer.go
blob: fe171b4195b4759c84a76d573aa971dc79815cc2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// This file is part of gnunet-go, a GNUnet-implementation in Golang.
// Copyright (C) 2019-2022 Bernd Fix  >Y<
//
// gnunet-go is free software: you can redistribute it and/or modify it
// under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// gnunet-go is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// SPDX-License-Identifier: AGPL3.0-or-later

package core

import (
	"encoding/base64"
	"fmt"
	"time"

	"gnunet/config"
	"gnunet/message"
	"gnunet/service/dht/blocks"
	"gnunet/util"

	"github.com/bfix/gospel/crypto/ed25519"
)

//----------------------------------------------------------------------
// GNUnet P2P network node (local or remote):
//
// * A LOCAL node has a long-term EdDSA key pair used for signing. The
//   public key is the node identifier (PeerID).
//   Local nodes hold additional attributes like ephemeral keys for message
//   exchange or a list of network addresses the node can be reached on.
//
// * A REMOTE node only has a public EdDSA key used by the local node
//   to verify signatures from the remote node.
//----------------------------------------------------------------------

// Peer represents a node in the GNUnet P2P network.
type Peer struct {
	prv      *ed25519.PrivateKey      // node private key (long-term signing key)
	pub      *ed25519.PublicKey       // node public key (=identifier)
	idString string                   // node identifier as string
	ephPrv   *ed25519.PrivateKey      // ephemeral signing key
	ephMsg   *message.EphemeralKeyMsg // ephemeral signing key message
}

//----------------------------------------------------------------------
// Create new peer objects
//----------------------------------------------------------------------

// NewLocalPeer creates a new local node from configuration data.
func NewLocalPeer(cfg *config.NodeConfig) (p *Peer, err error) {
	p = new(Peer)

	// get the key material for local node
	var data []byte
	if data, err = base64.StdEncoding.DecodeString(cfg.PrivateSeed); err != nil {
		return
	}
	p.prv = ed25519.NewPrivateKeyFromSeed(data)
	p.pub = p.prv.Public()
	p.idString = util.EncodeBinaryToString(p.pub.Bytes())
	p.ephPrv, p.ephMsg, err = message.NewEphemeralKey(p.pub.Bytes(), p.prv)
	if err != nil {
		return
	}
	return
}

// NewPeer instantiates a new (remote) peer object from given peer ID string.
func NewPeer(peerID string) (p *Peer, err error) {
	p = new(Peer)

	// get the key material for local node
	var data []byte
	if data, err = util.DecodeStringToBinary(peerID, 32); err != nil {
		return
	}
	p.prv = nil
	p.pub = ed25519.NewPublicKeyFromBytes(data)
	p.idString = util.EncodeBinaryToString(p.pub.Bytes())
	return
}

// Shutdown peer-related processes.
func (p *Peer) Shutdown() {}

//----------------------------------------------------------------------
//----------------------------------------------------------------------

// HelloData returns the current HELLO data for the peer. The list of listening
// endpoint addresses re passed in from core to reflect the actual active
// endpoints.
func (p *Peer) HelloData(ttl time.Duration, a []*util.Address) (h *blocks.HelloBlock, err error) {
	// assemble HELLO data
	h = new(blocks.HelloBlock)
	h.PeerID = p.GetID()
	h.Expire_ = util.NewAbsoluteTime(time.Now().Add(ttl))
	h.SetAddresses(a)

	// sign data
	sd := h.SignedData()
	var sig *ed25519.EdSignature
	if sig, err = p.prv.EdSign(sd); err != nil {
		return
	}
	err = h.SetSignature(util.NewPeerSignature(sig.Bytes()))
	return
}

// EphKeyMsg returns a new initialized message to negotiate session keys.
func (p *Peer) EphKeyMsg() *message.EphemeralKeyMsg {
	return p.ephMsg
}

// SetEphKeyMsg saves a template for new key negotiation messages.
func (p *Peer) SetEphKeyMsg(msg *message.EphemeralKeyMsg) {
	p.ephMsg = msg
}

// EphPrvKey returns the current ephemeral private key.
func (p *Peer) EphPrvKey() *ed25519.PrivateKey {
	return p.ephPrv
}

// PrvKey return the private key of the node.
func (p *Peer) PrvKey() *ed25519.PrivateKey {
	return p.prv
}

// PubKey return the public key of the node.
func (p *Peer) PubKey() *ed25519.PublicKey {
	return p.pub
}

// GetID returns the node ID (public key) in binary format
func (p *Peer) GetID() *util.PeerID {
	return util.NewPeerID(p.pub.Bytes())
}

// GetIDString returns the string representation of the public key of the node.
func (p *Peer) GetIDString() string {
	return p.idString
}

// Sign a message with the (long-term) private key.
func (p *Peer) Sign(msg []byte) (*ed25519.EdSignature, error) {
	if p.prv == nil {
		return nil, fmt.Errorf("no private key")
	}
	return p.prv.EdSign(msg)
}

// Verify a message signature with the public key of a peer.
func (p *Peer) Verify(msg []byte, sig *ed25519.EdSignature) (bool, error) {
	return p.pub.EdVerify(msg, sig)
}