remove ID private key from LNDConn struct

This commit is contained in:
Tadge Dryja 2016-01-17 11:20:40 -08:00
parent 9e5f302288
commit b0a402bc4f
3 changed files with 90 additions and 87 deletions

@ -16,18 +16,16 @@ import (
)
// Conn...
type Conn struct {
longTermPriv *btcec.PrivateKey
remotePub *btcec.PublicKey
remoteLNId [16]byte
type LNDConn struct {
RemotePub *btcec.PublicKey
RemoteLNId [16]byte
myNonceInt uint64
remoteNonceInt uint64
// If Authed == false, the remotePub is the EPHEMERAL key.
// once authed == true, remotePub is who you're actually talking to.
authed bool
Authed bool
// chachaStream saves some time as you don't have to init it with
// the session key every time. Make SessionKey redundant; remove later.
@ -37,26 +35,27 @@ type Conn struct {
// encapsulated PBX connection.
// If going ViaPbx, Cn isn't used channels are used for Read() and
// Write(), which are filled by the PBXhandler.
viaPbx bool
pbxIncoming chan []byte
pbxOutgoing chan []byte
ViaPbx bool
PbxIncoming chan []byte
PbxOutgoing chan []byte
version uint8
readBuf bytes.Buffer
conn net.Conn
Conn net.Conn
}
// NewConn...
func NewConn(connPrivKey *btcec.PrivateKey, conn net.Conn) *Conn {
return &Conn{longTermPriv: connPrivKey, conn: conn}
func NewConn(conn net.Conn) *LNDConn {
return &LNDConn{Conn: conn}
}
// Dial...
func (c *Conn) Dial(address string, remoteId []byte) error {
func (c *LNDConn) Dial(
myId *btcec.PrivateKey, address string, remoteId []byte) error {
var err error
if c.conn != nil {
if c.Conn != nil {
return fmt.Errorf("connection already established")
}
@ -68,7 +67,7 @@ func (c *Conn) Dial(address string, remoteId []byte) error {
}
// First, open the TCP connection itself.
c.conn, err = net.Dial("tcp", address)
c.Conn, err = net.Dial("tcp", address)
if err != nil {
return err
}
@ -76,10 +75,10 @@ func (c *Conn) Dial(address string, remoteId []byte) error {
// Calc remote LNId; need this for creating pbx connections just because
// LNid is in the struct does not mean it's authed!
if len(remoteId) == 20 {
copy(c.remoteLNId[:], remoteId[:16])
copy(c.RemoteLNId[:], remoteId[:16])
} else {
theirAdr := btcutil.Hash160(remoteId)
copy(c.remoteLNId[:], theirAdr[:16])
copy(c.RemoteLNId[:], theirAdr[:16])
}
// Make up an ephemeral keypair for this session.
@ -90,12 +89,12 @@ func (c *Conn) Dial(address string, remoteId []byte) error {
ourEphemeralPub := ourEphemeralPriv.PubKey()
// Sned 1. Send my ephemeral pubkey. Can add version bits.
if _, err = writeClear(c.conn, ourEphemeralPub.SerializeCompressed()); err != nil {
if _, err = writeClear(c.Conn, ourEphemeralPub.SerializeCompressed()); err != nil {
return err
}
// Read, then deserialize their ephemeral public key.
theirEphPubBytes, err := readClear(c.conn)
theirEphPubBytes, err := readClear(c.Conn)
if err != nil {
return err
}
@ -124,17 +123,17 @@ func (c *Conn) Dial(address string, remoteId []byte) error {
c.myNonceInt = 1 << 63
c.remoteNonceInt = 0
c.remotePub = theirEphPub
c.authed = false
c.RemotePub = theirEphPub
c.Authed = false
// Session is now open and confidential but not yet authenticated...
// So auth!
if len(remoteId) == 20 {
// Only know pubkey hash (20 bytes).
err = c.authPKH(remoteId, ourEphemeralPub.SerializeCompressed())
err = c.authPKH(myId, remoteId, ourEphemeralPub.SerializeCompressed())
} else {
// Must be 33 byte pubkey.
err = c.authPubKey(remoteId, ourEphemeralPub.SerializeCompressed())
err = c.authPubKey(myId, remoteId, ourEphemeralPub.SerializeCompressed())
}
if err != nil {
return err
@ -144,9 +143,10 @@ func (c *Conn) Dial(address string, remoteId []byte) error {
}
// authPubKey...
func (c *Conn) authPubKey(remotePubBytes, localEphPubBytes []byte) error {
if c.authed {
return fmt.Errorf("%s already authed", c.remotePub)
func (c *LNDConn) authPubKey(
myId *btcec.PrivateKey, remotePubBytes, localEphPubBytes []byte) error {
if c.Authed {
return fmt.Errorf("%s already authed", c.RemotePub)
}
// Since we already know their public key, we can immediately generate
@ -156,22 +156,22 @@ func (c *Conn) authPubKey(remotePubBytes, localEphPubBytes []byte) error {
return err
}
theirPKH := btcutil.Hash160(remotePubBytes)
idDH := fastsha256.Sum256(btcec.GenerateSharedSecret(c.longTermPriv, theirPub))
myDHproof := btcutil.Hash160(append(c.remotePub.SerializeCompressed(), idDH[:]...))
idDH := fastsha256.Sum256(btcec.GenerateSharedSecret(myId, theirPub))
myDHproof := btcutil.Hash160(append(c.RemotePub.SerializeCompressed(), idDH[:]...))
// Send over the 73 byte authentication message: my pubkey, their
// pubkey hash, DH proof.
var authMsg [73]byte
copy(authMsg[:33], c.longTermPriv.PubKey().SerializeCompressed())
copy(authMsg[:33], myId.PubKey().SerializeCompressed())
copy(authMsg[33:], theirPKH)
copy(authMsg[53:], myDHproof)
if _, err = c.conn.Write(authMsg[:]); err != nil {
if _, err = c.Conn.Write(authMsg[:]); err != nil {
return nil
}
// Await, their response. They should send only the 20-byte DH proof.
resp := make([]byte, 20)
_, err = c.conn.Read(resp)
_, err = c.Conn.Read(resp)
if err != nil {
return err
}
@ -183,18 +183,19 @@ func (c *Conn) authPubKey(remotePubBytes, localEphPubBytes []byte) error {
}
// Proof checks out, auth complete.
c.remotePub = theirPub
c.RemotePub = theirPub
theirAdr := btcutil.Hash160(theirPub.SerializeCompressed())
copy(c.remoteLNId[:], theirAdr[:16])
c.authed = true
copy(c.RemoteLNId[:], theirAdr[:16])
c.Authed = true
return nil
}
// authPKH...
func (c *Conn) authPKH(theirPKH, localEphPubBytes []byte) error {
if c.authed {
return fmt.Errorf("%s already authed", c.remotePub)
func (c *LNDConn) authPKH(
myId *btcec.PrivateKey, theirPKH, localEphPubBytes []byte) error {
if c.Authed {
return fmt.Errorf("%s already authed", c.RemotePub)
}
if len(theirPKH) != 20 {
return fmt.Errorf("remote PKH must be 20 bytes, got %d",
@ -203,9 +204,9 @@ func (c *Conn) authPKH(theirPKH, localEphPubBytes []byte) error {
// Send 53 bytes: our pubkey, and the remote's pubkey hash.
var greetingMsg [53]byte
copy(greetingMsg[:33], c.longTermPriv.PubKey().SerializeCompressed())
copy(greetingMsg[:33], myId.PubKey().SerializeCompressed())
copy(greetingMsg[:33], theirPKH)
if _, err := c.conn.Write(greetingMsg[:]); err != nil {
if _, err := c.Conn.Write(greetingMsg[:]); err != nil {
return err
}
@ -214,7 +215,7 @@ func (c *Conn) authPKH(theirPKH, localEphPubBytes []byte) error {
// * NOTE(roasbeef): read timeout should be set on the underlying
// net.Conn.
resp := make([]byte, 53)
if _, err := c.conn.Read(resp); err != nil {
if _, err := c.Conn.Read(resp); err != nil {
return err
}
@ -223,7 +224,7 @@ func (c *Conn) authPKH(theirPKH, localEphPubBytes []byte) error {
if err != nil {
return err
}
idDH := fastsha256.Sum256(btcec.GenerateSharedSecret(c.longTermPriv, theirPub))
idDH := fastsha256.Sum256(btcec.GenerateSharedSecret(myId, theirPub))
fmt.Printf("made idDH %x\n", idDH)
theirDHproof := btcutil.Hash160(append(localEphPubBytes, idDH[:]...))
@ -233,16 +234,16 @@ func (c *Conn) authPKH(theirPKH, localEphPubBytes []byte) error {
}
// If their DH proof checks out, then send our own.
myDHproof := btcutil.Hash160(append(c.remotePub.SerializeCompressed(), idDH[:]...))
if _, err = c.conn.Write(myDHproof); err != nil {
myDHproof := btcutil.Hash160(append(c.RemotePub.SerializeCompressed(), idDH[:]...))
if _, err = c.Conn.Write(myDHproof); err != nil {
return err
}
// Proof sent, auth complete.
c.remotePub = theirPub
c.RemotePub = theirPub
theirAdr := btcutil.Hash160(theirPub.SerializeCompressed())
copy(c.remoteLNId[:], theirAdr[:16])
c.authed = true
copy(c.RemoteLNId[:], theirAdr[:16])
c.Authed = true
return nil
}
@ -251,7 +252,7 @@ func (c *Conn) authPKH(theirPKH, localEphPubBytes []byte) error {
// Read can be made to time out and return a Error with Timeout() == true
// after a fixed time limit; see SetDeadline and SetReadDeadline.
// Part of the net.Conn interface.
func (c *Conn) Read(b []byte) (n int, err error) {
func (c *LNDConn) Read(b []byte) (n int, err error) {
// In order to reconcile the differences between the record abstraction
// of our AEAD connection, and the stream abstraction of TCP, we maintain
// an intermediate read buffer. If this buffer becomes depleated, then
@ -259,7 +260,7 @@ func (c *Conn) Read(b []byte) (n int, err error) {
// read directly from the buffer.
if c.readBuf.Len() == 0 {
// The buffer is empty, so read the next cipher text.
ctext, err := readClear(c.conn)
ctext, err := readClear(c.Conn)
if err != nil {
return 0, err
}
@ -270,7 +271,7 @@ func (c *Conn) Read(b []byte) (n int, err error) {
binary.BigEndian.PutUint64(nonceBuf[:], c.remoteNonceInt)
fmt.Printf("decrypt %d byte from %x nonce %d\n",
len(ctext), c.remoteLNId, c.remoteNonceInt)
len(ctext), c.RemoteLNId, c.remoteNonceInt)
c.remoteNonceInt++ // increment remote nonce, no matter what...
@ -292,12 +293,12 @@ func (c *Conn) Read(b []byte) (n int, err error) {
// Write can be made to time out and return a Error with Timeout() == true
// after a fixed time limit; see SetDeadline and SetWriteDeadline.
// Part of the net.Conn interface.
func (c *Conn) Write(b []byte) (n int, err error) {
func (c *LNDConn) Write(b []byte) (n int, err error) {
if b == nil {
return 0, fmt.Errorf("write to %x nil", c.remoteLNId)
return 0, fmt.Errorf("write to %x nil", c.RemoteLNId)
}
fmt.Printf("Encrypt %d byte plaintext to %x nonce %d\n",
len(b), c.remoteLNId, c.myNonceInt)
len(b), c.RemoteLNId, c.myNonceInt)
// first encrypt message with shared key
var nonceBuf [8]byte
@ -310,50 +311,50 @@ func (c *Conn) Write(b []byte) (n int, err error) {
}
if len(ctext) > 65530 {
return 0, fmt.Errorf("Write to %x too long, %d bytes",
c.remoteLNId, len(ctext))
c.RemoteLNId, len(ctext))
}
// use writeClear to prepend length / destination header
return writeClear(c.conn, ctext)
return writeClear(c.Conn, ctext)
}
// Close closes the connection.
// Any blocked Read or Write operations will be unblocked and return errors.
// Part of the net.Conn interface.
func (c *Conn) Close() error {
func (c *LNDConn) Close() error {
c.myNonceInt = 0
c.remoteNonceInt = 0
c.remotePub = nil
c.RemotePub = nil
return c.conn.Close()
return c.Conn.Close()
}
// LocalAddr returns the local network address.
// Part of the net.Conn interface.
// If PBX reports address of pbx host.
func (c *Conn) LocalAddr() net.Addr {
return c.conn.LocalAddr()
func (c *LNDConn) LocalAddr() net.Addr {
return c.Conn.LocalAddr()
}
// RemoteAddr returns the remote network address.
// Part of the net.Conn interface.
func (c *Conn) RemoteAddr() net.Addr {
return c.conn.RemoteAddr()
func (c *LNDConn) RemoteAddr() net.Addr {
return c.Conn.RemoteAddr()
}
// SetDeadline sets the read and write deadlines associated
// with the connection. It is equivalent to calling both
// SetReadDeadline and SetWriteDeadline.
// Part of the net.Conn interface.
func (c *Conn) SetDeadline(t time.Time) error {
return c.conn.SetDeadline(t)
func (c *LNDConn) SetDeadline(t time.Time) error {
return c.Conn.SetDeadline(t)
}
// SetReadDeadline sets the deadline for future Read calls.
// A zero value for t means Read will not time out.
// Part of the net.Conn interface.
func (c *Conn) SetReadDeadline(t time.Time) error {
return c.conn.SetReadDeadline(t)
func (c *LNDConn) SetReadDeadline(t time.Time) error {
return c.Conn.SetReadDeadline(t)
}
// SetWriteDeadline sets the deadline for future Write calls.
@ -361,8 +362,8 @@ func (c *Conn) SetReadDeadline(t time.Time) error {
// some of the data was successfully written.
// A zero value for t means Write will not time out.
// Part of the net.Conn interface.
func (c *Conn) SetWriteDeadline(t time.Time) error {
return c.conn.SetWriteDeadline(t)
func (c *LNDConn) SetWriteDeadline(t time.Time) error {
return c.Conn.SetWriteDeadline(t)
}
var _ net.Conn = (*Conn)(nil)
var _ net.Conn = (*LNDConn)(nil)

@ -43,7 +43,7 @@ func (l *Listener) Accept() (c net.Conn, err error) {
return nil, nil
}
lndc := NewConn(l.longTermPriv, conn)
lndc := NewConn(conn)
// Exchange an ephemeral public key with the remote connection in order
// to establish a confidential connection before we attempt to
@ -56,7 +56,7 @@ func (l *Listener) Accept() (c net.Conn, err error) {
// Now that we've established an encrypted connection, authenticate the
// identity of the remote host.
ephemeralPub := ephemeralKey.PubKey().SerializeCompressed()
if err := l.authenticateConnection(lndc, ephemeralPub); err != nil {
if err := l.authenticateConnection(l.longTermPriv, lndc, ephemeralPub); err != nil {
lndc.Close()
return nil, err
}
@ -65,12 +65,12 @@ func (l *Listener) Accept() (c net.Conn, err error) {
}
// createCipherConn....
func (l *Listener) createCipherConn(lnConn *Conn) (*btcec.PrivateKey, error) {
func (l *Listener) createCipherConn(lnConn *LNDConn) (*btcec.PrivateKey, error) {
var err error
var theirEphPubBytes []byte
// First, read and deserialize their ephemeral public key.
theirEphPubBytes, err = readClear(lnConn.conn)
theirEphPubBytes, err = readClear(lnConn.Conn)
if err != nil {
return nil, err
}
@ -89,7 +89,7 @@ func (l *Listener) createCipherConn(lnConn *Conn) (*btcec.PrivateKey, error) {
if err != nil {
return nil, err
}
if _, err := writeClear(lnConn.conn, myEph.PubKey().SerializeCompressed()); err != nil {
if _, err := writeClear(lnConn.Conn, myEph.PubKey().SerializeCompressed()); err != nil {
return nil, err
}
@ -107,19 +107,20 @@ func (l *Listener) createCipherConn(lnConn *Conn) (*btcec.PrivateKey, error) {
lnConn.remoteNonceInt = 1 << 63
lnConn.myNonceInt = 0
lnConn.remotePub = theirEphPub
lnConn.authed = false
lnConn.RemotePub = theirEphPub
lnConn.Authed = false
return myEph, nil
}
// AuthListen...
func (l *Listener) authenticateConnection(lnConn *Conn, localEphPubBytes []byte) error {
func (l *Listener) authenticateConnection(
myId *btcec.PrivateKey, lnConn *LNDConn, localEphPubBytes []byte) error {
var err error
// TODO(roasbeef): should be using read/write clear here?
slice := make([]byte, 73)
n, err := lnConn.conn.Read(slice)
n, err := lnConn.Conn.Read(slice)
if err != nil {
fmt.Printf("Read error: %s\n", err.Error())
return err
@ -144,11 +145,11 @@ func (l *Listener) authenticateConnection(lnConn *Conn, localEphPubBytes []byte)
return err
}
idDH := fastsha256.Sum256(
btcec.GenerateSharedSecret(lnConn.longTermPriv, theirPub),
btcec.GenerateSharedSecret(l.longTermPriv, theirPub),
)
myDHproof := btcutil.Hash160(
append(lnConn.remotePub.SerializeCompressed(), idDH[:]...),
append(lnConn.RemotePub.SerializeCompressed(), idDH[:]...),
)
theirDHproof := btcutil.Hash160(append(localEphPubBytes, idDH[:]...))
@ -162,19 +163,19 @@ func (l *Listener) authenticateConnection(lnConn *Conn, localEphPubBytes []byte)
}
// Their DH proof checks out, so send ours now.
if _, err = lnConn.conn.Write(myDHproof); err != nil {
if _, err = lnConn.Conn.Write(myDHproof); err != nil {
return err
}
} else {
// Otherwise, they don't yet know our public key. So we'll send
// it over to them, so we can both compute the DH proof.
msg := append(l.longTermPriv.PubKey().SerializeCompressed(), myDHproof...)
if _, err = lnConn.conn.Write(msg); err != nil {
if _, err = lnConn.Conn.Write(msg); err != nil {
return err
}
resp := make([]byte, 20)
if _, err := lnConn.conn.Read(resp); err != nil {
if _, err := lnConn.Conn.Read(resp); err != nil {
return err
}
@ -185,9 +186,9 @@ func (l *Listener) authenticateConnection(lnConn *Conn, localEphPubBytes []byte)
}
theirAdr := btcutil.Hash160(theirPub.SerializeCompressed())
copy(lnConn.remoteLNId[:], theirAdr[:16])
lnConn.remotePub = theirPub
lnConn.authed = true
copy(lnConn.RemoteLNId[:], theirAdr[:16])
lnConn.RemotePub = theirPub
lnConn.Authed = true
return nil
}

@ -155,8 +155,9 @@ out:
// breaks down, then return an error to the
// caller.
ipAddr := addr.NetAddr.String()
conn := lndc.NewConn(s.longTermPriv, nil)
if err := conn.Dial(ipAddr, remoteId); err != nil {
conn := lndc.NewConn(nil)
if err := conn.Dial(
s.longTermPriv, ipAddr, remoteId); err != nil {
msg.reply <- err
}