Documentation ¶
Overview ¶
Package handshake contains the code that implements authentication handshake performed when a new connection between two peers is established, as described in the network security implementation [RFC], section 1.2.3 and 1.2.4.
Each peer wanting to join a network needs to provide a proof of ownership of an on-chain identity with an associated stake. As part of the network join handshake, peer responding to the handshake will also provide proof of its own stake. The same handshake is executed when two peers already being a part of the network establish a new connection with each other.
The handshake is a 3-round procedure when two parties called initiator and responder exchange messages. The entire handshake procedure can be described with the following diagram:
INITIATOR RESPONDER ¶
[Act 1] nonce1 = random_nonce() act1Message{nonce1, protocol_id1} ---->
[Act 2] nonce2 = random_nonce() challenge = sha256(nonce1 || nonce2) <---- act2Message{challenge, nonce2, protocol_id2}
[Act 3] challenge = sha256(nonce1 || nonce2) act3Message{challenge} ---->
act1Message, act2Message, and act3Message are messages exchanged between initiator and responder in acts one, two, and three of the handshake, respectively.
InitiatorAct1, InitiatorAct2, and InitiatorAct3 represent the state of the initiator in rounds one, two, and three of the handshake, respectively.
ResponderAct2 and ResponderAct3 represent the state of the responder in rounds two and three of the handshake, respectively. Since the first act of the handshake is initiated by the initiator and the responder has no internal state before receiving the first message, there is no representation for responder state in the act one.
[RFC]: /docs/rfc/rfc-2-network-security-implementation.adoc
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Act1Message ¶
type Act1Message struct {
// contains filtered or unexported fields
}
Act1Message is sent in the first handshake act by the initiator to the responder. It contains randomly generated `nonce1`, an 8-byte (64-bit) unsigned integer as well as the protocol identifier.
act1Message should be signed with initiator's static private key.
func (*Act1Message) Marshal ¶
func (am *Act1Message) Marshal() ([]byte, error)
Marshal converts this Act1Message to a byte array suitable for network communication.
func (*Act1Message) Unmarshal ¶
func (am *Act1Message) Unmarshal(bytes []byte) error
Unmarshal converts a byte array produced by Marshal to a Act1Message.
type Act2Message ¶
type Act2Message struct {
// contains filtered or unexported fields
}
Act2Message is sent in the second handshake act by the responder to the initiator. It contains randomly generated `nonce2`, which is an 8-byte unsigned integer, `challenge`, which is the result of SHA256 on the concatenated bytes of `nonce1` and `nonce2`, and the protocol identifier.
act2Message should be signed with responder's static private key.
func (*Act2Message) Marshal ¶
func (am *Act2Message) Marshal() ([]byte, error)
Marshal converts this Act2Message to a byte array suitable for network communication.
func (*Act2Message) Unmarshal ¶
func (am *Act2Message) Unmarshal(bytes []byte) error
Unmarshal converts a byte array produced by Marshal to a Act2Message.
type Act3Message ¶
type Act3Message struct {
// contains filtered or unexported fields
}
Act3Message is sent in the third handshake act by the initiator to the responder. It contains the challenge that has been recomputed by the initiator as a SHA256 of the concatenated bytes of `nonce1` and `nonce2`.
act3Message should be signed with initiator's static private key.
func (*Act3Message) Marshal ¶
func (am *Act3Message) Marshal() ([]byte, error)
Marshal converts this Act3Message to a byte array suitable for network communication.
func (*Act3Message) Unmarshal ¶
func (am *Act3Message) Unmarshal(bytes []byte) error
Unmarshal converts a byte array produced by Marshal to a Act3Message.
type InitiatorAct1 ¶ added in v1.21.0
type InitiatorAct1 struct {
// contains filtered or unexported fields
}
InitiatorAct1 represents the state of the initiator in the first act of the handshake protocol.
func InitiateHandshake ¶
func InitiateHandshake(protocol string) (*InitiatorAct1, error)
InitiateHandshake function allows to initiate a handshake by creating and initializing a state machine representing initiator in the first round of the handshake, ready to execute the protocol.
func (*InitiatorAct1) Message ¶ added in v1.21.0
func (ia1 *InitiatorAct1) Message() *Act1Message
Message returns the message sent by initiator to the responder in the first act of the handshake protocol.
func (*InitiatorAct1) Next ¶ added in v1.21.0
func (ia1 *InitiatorAct1) Next() *InitiatorAct2
Next performs a state transition and returns initiator in a state ready to execute the second act of the handshake protocol.
type InitiatorAct2 ¶ added in v1.21.0
type InitiatorAct2 struct {
// contains filtered or unexported fields
}
InitiatorAct2 represents the state of the initiator in the second act of the handshake protocol.
func (*InitiatorAct2) Next ¶ added in v1.21.0
func (ia2 *InitiatorAct2) Next(message *Act2Message) (*InitiatorAct3, error)
Next performs a state transition and returns initiator in a state ready to execute the third act of the handshake protocol.
Function validates the challenge received from responder in the second act of the protocol. If the challenge is the same as expected one, new state of initiator is returned. Otherwise, function reports an error and handshake protocol should be immediately aborted.
The function also validates if both parties run the same protocol.
type InitiatorAct3 ¶ added in v1.21.0
type InitiatorAct3 struct {
// contains filtered or unexported fields
}
InitiatorAct3 represents the state of the initiator in the third act of the handshake protocol.
func (*InitiatorAct3) Message ¶ added in v1.21.0
func (ia3 *InitiatorAct3) Message() *Act3Message
Message returns the message sent by initiator to the responder in the third act of the handshake protocol.
type ResponderAct2 ¶ added in v1.21.0
type ResponderAct2 struct {
// contains filtered or unexported fields
}
ResponderAct2 represents the state of the responder in the second act of the handshake protocol.
func AnswerHandshake ¶
func AnswerHandshake(message *Act1Message, protocol string) (*ResponderAct2, error)
AnswerHandshake is used to initiate a responder as a result of receiving message from initiator in the first act of the handshake protocol. The returned responder is in a state ready to execute the second act of the handshake protocol. The function also validates if both parties run the same protocol.
func (*ResponderAct2) Message ¶ added in v1.21.0
func (ra2 *ResponderAct2) Message() *Act2Message
Message returns the message sent by responder to the initiator in the second act of the handshake protocol.
func (*ResponderAct2) Next ¶ added in v1.21.0
func (ra2 *ResponderAct2) Next() *ResponderAct3
Next performs a state transition and returns responder in a state ready to execute the third act of the handshake protocol.
type ResponderAct3 ¶ added in v1.21.0
type ResponderAct3 struct {
// contains filtered or unexported fields
}
ResponderAct3 represents the state of the responder in the third act of the handshake protocol.
func (*ResponderAct3) FinalizeHandshake ¶ added in v1.21.0
func (ra3 *ResponderAct3) FinalizeHandshake(message *Act3Message) error
FinalizeHandshake is used in the third act of the handshake protocol to inform responder about a message sent by initiator. Responder validates the challenge in the message comparing it with the one expected. If both challenges are equal, handshake has completed successfully and function returns nil. Otherwise, if challenge is not as expected, function returns an error and it means the handshake protocol failed.