184 lines
5.0 KiB
Go
184 lines
5.0 KiB
Go
package wire
|
|
|
|
import (
|
|
"net"
|
|
|
|
"github.com/Indra-Labs/indra/pkg/ifc"
|
|
"github.com/Indra-Labs/indra/pkg/key/pub"
|
|
"github.com/Indra-Labs/indra/pkg/message"
|
|
"github.com/Indra-Labs/indra/pkg/nonce"
|
|
)
|
|
|
|
// MagicLen is 3 to make it nearly impossible that the wrong cipher will yield a
|
|
// valid Magic string as listed below.
|
|
const MagicLen = 3
|
|
|
|
type MessageMagic string
|
|
|
|
type Message interface {
|
|
Encode() (o ifc.Message)
|
|
}
|
|
|
|
var (
|
|
ForwardMagic = MessageMagic("fwd")
|
|
ExitMagic = MessageMagic("exi")
|
|
ReturnMagic = MessageMagic("rtn")
|
|
CipherMagic = MessageMagic("cif")
|
|
PurchaseMagic = MessageMagic("prc")
|
|
SessionMagic = MessageMagic("ses")
|
|
)
|
|
|
|
// Forward is just an IP address and a wrapper for another message.
|
|
type Forward struct {
|
|
*message.Addresses
|
|
net.IP
|
|
Message
|
|
}
|
|
|
|
func (fw *Forward) Encode() (o ifc.Message) {
|
|
ipLen := len(fw.IP)
|
|
msg := fw.Message.Encode()
|
|
msg, _ = message.Encode(fw.To, fw.From, msg)
|
|
fwd := make([]byte, ipLen+1)
|
|
fwd[0] = byte(ipLen)
|
|
copy(fwd[1:], fw.IP)
|
|
o = append(append(ifc.Message(ForwardMagic), fwd...), msg...)
|
|
return
|
|
|
|
}
|
|
|
|
func DecodeForward(msg ifc.Message) (rm *Forward, e error) {
|
|
return
|
|
}
|
|
|
|
// Exit messages are the layer of a message after two Forward packets that
|
|
// provides an exit address and
|
|
type Exit struct {
|
|
*message.Addresses
|
|
// Port identifies the type of service as well as being the port used
|
|
// by the service to be relayed to. Notice there is no IP address, this
|
|
// is because Indranet only forwards to exits of decentralised services
|
|
// also running on the same machine. This service could be a proxy, of
|
|
// course, if configured this way.
|
|
Port uint16
|
|
// Cipher is a set of 3 symmetric ciphers that are to be used in their
|
|
// given order over the reply message from the service.
|
|
Cipher [3][32]byte
|
|
// Return is the encoded message with the three hops using the Return
|
|
// keys for the relevant relays, encrypted progressively. Note that this
|
|
// message uses a different Cipher than the one above
|
|
Return ifc.Message
|
|
Message
|
|
}
|
|
|
|
func (ex *Exit) Encode() (o ifc.Message) {
|
|
msg := ex.Message.Encode()
|
|
msg, _ = message.Encode(ex.To, ex.From, msg)
|
|
return
|
|
}
|
|
|
|
func DecodeExit(msg ifc.Message) (rm *Exit, e error) {
|
|
return
|
|
}
|
|
|
|
// Return messages are distinct from Forward messages in that the header
|
|
// encryption uses a different secret than the payload. Relays identify this by
|
|
// encrypting the first 16 bytes of the header and if one of the magic bytes is
|
|
// not found
|
|
type Return struct {
|
|
*message.Addresses
|
|
nonce.ID
|
|
// IP is the address of the next relay in the return leg of a circuit.
|
|
net.IP
|
|
Message
|
|
}
|
|
|
|
func (rt *Return) Encode() (o ifc.Message) {
|
|
msg := rt.Message.Encode()
|
|
msg, _ = message.Encode(rt.To, rt.From, msg)
|
|
return
|
|
}
|
|
|
|
func DecodeReturn(msg ifc.Message) (rm *Return, e error) {
|
|
return
|
|
}
|
|
|
|
// Cipher delivers a public key to be used in association with a Return with the
|
|
// matching ID. This is wrapped in two Forward messages and contains two layers
|
|
// of Forward messages, ensuring that the node cannot discover where this comes
|
|
// from but allows a Return public key to be provided for a Purchase.
|
|
type Cipher struct {
|
|
*message.Addresses
|
|
nonce.ID
|
|
Key pub.Bytes
|
|
Forward
|
|
}
|
|
|
|
func (ci *Cipher) Encode() (o ifc.Message) {
|
|
msg := ci.Forward.Encode()
|
|
msg, _ = message.Encode(ci.To, ci.From, msg)
|
|
return
|
|
}
|
|
|
|
func DecodeCipher(msg ifc.Message) (rm *Cipher, e error) {
|
|
return
|
|
}
|
|
|
|
// Purchase is a message that is sent after first forwarding a Lighting payment
|
|
// of an amount corresponding to the number of bytes requested based on the
|
|
// price advertised for Exit traffic by a relay. The Receipt is the confirmation
|
|
// after requesting an Invoice for the amount and then paying it.
|
|
//
|
|
// This message contains a Return message, which enables payments to proxy
|
|
// forwards through two hops to the router that will issue the Session, plus two
|
|
// more Return layers for carrying the Session back to the client.
|
|
type Purchase struct {
|
|
*message.Addresses
|
|
Bytes int
|
|
Receipt ifc.Message
|
|
Return
|
|
}
|
|
|
|
func (pr *Purchase) Encode() (o ifc.Message) {
|
|
msg := pr.Return.Encode()
|
|
msg, _ = message.Encode(pr.To, pr.From, msg)
|
|
return
|
|
}
|
|
|
|
func DecodePurchase(msg ifc.Message) (rm *Purchase, e error) {
|
|
return
|
|
}
|
|
|
|
// Session is a message containing two public keys which identify to a relay the
|
|
// session to account bytes on, this is wrapped in two Return message layers by
|
|
// the seller. Forward keys are used for encryption in Forward and Exit
|
|
// messages, and Return keys are separate and are only known to the client and
|
|
// relay that issues a Session, ensuring that the Exit cannot see the inner
|
|
// layers of the Return messages.
|
|
type Session struct {
|
|
*message.Addresses
|
|
ForwardKey pub.Bytes
|
|
ReturnKey pub.Bytes
|
|
Return
|
|
}
|
|
|
|
func (se *Session) Encode() (o ifc.Message) {
|
|
msg := se.Return.Encode()
|
|
msg, _ = message.Encode(se.To, se.From, msg)
|
|
return
|
|
}
|
|
|
|
func DecodeSession(msg ifc.Message) (rm *Session, e error) {
|
|
return
|
|
}
|
|
|
|
type Raw struct {
|
|
*message.Addresses
|
|
Bytes []byte
|
|
}
|
|
|
|
func (r Raw) Encode() (o ifc.Message) {
|
|
o, _ = message.Encode(r.To, r.From, r.Bytes)
|
|
return
|
|
}
|