proxy connection through secio

This commit is contained in:
Dmitriy Ryajov 2019-09-13 12:01:14 -06:00
parent 2d00f6a6db
commit ea142f0e6d
1 changed files with 31 additions and 17 deletions

View File

@ -1,3 +1,4 @@
## Nim-LibP2P ## Nim-LibP2P
## Copyright (c) 2018 Status Research & Development GmbH ## Copyright (c) 2018 Status Research & Development GmbH
## Licensed under either of ## Licensed under either of
@ -13,8 +14,8 @@ import secure,
../../crypto/crypto, ../../crypto/crypto,
../../crypto/ecnist, ../../crypto/ecnist,
../../protobuf/minprotobuf, ../../protobuf/minprotobuf,
../../peer ../../peer,
../../stream/bufferstream
export hmac, sha2, sha, hash, rijndael, bcmode export hmac, sha2, sha, hash, rijndael, bcmode
logScope: logScope:
@ -59,7 +60,8 @@ type
of SecureMacType.Sha1: of SecureMacType.Sha1:
ctxsha1: HMAC[sha1] ctxsha1: HMAC[sha1]
SecureConnection* = ref object of BufferStream SecureConnection* = ref object of Connection
conn*: Connection
writerMac: SecureMac writerMac: SecureMac
readerMac: SecureMac readerMac: SecureMac
writerCoder: SecureCipher writerCoder: SecureCipher
@ -212,7 +214,7 @@ proc writeMessage*(sconn: SecureConnection, message: seq[byte]) {.async.} =
msg[3] = byte(length and 0xFF) msg[3] = byte(length and 0xFF)
trace "Writing message", message = toHex(msg) trace "Writing message", message = toHex(msg)
try: try:
await sconn.pushTo(msg) await sconn.conn.write(msg)
except AsyncStreamWriteError: except AsyncStreamWriteError:
debug "Could not write to connection" debug "Could not write to connection"
@ -265,7 +267,7 @@ proc transactMessage(conn: Connection,
except AsyncStreamWriteError: except AsyncStreamWriteError:
trace "Could not write to connection", conn = conn trace "Could not write to connection", conn = conn
proc handshake*(p: Secio, conn: Connection) {.async.} = proc handshake*(s: Secio, conn: Connection): Future[SecureConnection] {.async.} =
var var
localNonce: array[SecioNonceSize, byte] localNonce: array[SecioNonceSize, byte]
remoteNonce: seq[byte] remoteNonce: seq[byte]
@ -281,7 +283,7 @@ proc handshake*(p: Secio, conn: Connection) {.async.} =
remotePeerId: PeerID remotePeerId: PeerID
localPeerId: PeerID localPeerId: PeerID
ekey: PrivateKey ekey: PrivateKey
localBytesPubkey = p.localPublicKey.getBytes() localBytesPubkey = s.localPublicKey.getBytes()
if randomBytes(localNonce) != SecioNonceSize: if randomBytes(localNonce) != SecioNonceSize:
raise newException(CatchableError, "Could not generate random data") raise newException(CatchableError, "Could not generate random data")
@ -289,7 +291,7 @@ proc handshake*(p: Secio, conn: Connection) {.async.} =
var request = createProposal(localNonce, localBytesPubkey, SecioExchanges, var request = createProposal(localNonce, localBytesPubkey, SecioExchanges,
SecioCiphers, SecioHashes) SecioCiphers, SecioHashes)
localPeerId = PeerID.init(p.localPublicKey) localPeerId = PeerID.init(s.localPublicKey)
debug "Local proposal", schemes = SecioExchanges, ciphers = SecioCiphers, debug "Local proposal", schemes = SecioExchanges, ciphers = SecioCiphers,
hashes = SecioHashes, hashes = SecioHashes,
@ -336,7 +338,7 @@ proc handshake*(p: Secio, conn: Connection) {.async.} =
# We need EC public key in raw binary form # We need EC public key in raw binary form
var epubkey = ekeypair.pubkey.eckey.getRawBytes() var epubkey = ekeypair.pubkey.eckey.getRawBytes()
var localCorpus = request[4..^1] & answer & epubkey var localCorpus = request[4..^1] & answer & epubkey
var signature = p.localPrivateKey.sign(localCorpus) var signature = s.localPrivateKey.sign(localCorpus)
var localExchange = createExchange(epubkey, signature.getBytes()) var localExchange = createExchange(epubkey, signature.getBytes())
@ -387,25 +389,37 @@ proc handshake*(p: Secio, conn: Connection) {.async.} =
# Perform Nonce exchange over encrypted channel. # Perform Nonce exchange over encrypted channel.
var sconn = newSecureConnection(conn, hash, cipher, keys, order) result = newSecureConnection(conn, hash, cipher, keys, order)
await sconn.writeMessage(remoteNonce) await result.writeMessage(remoteNonce)
var res = await sconn.readMessage() var res = await result.readMessage()
if res != @localNonce: if res != @localNonce:
debug "Nonce verification failed", receivedNonce = toHex(res), debug "Nonce verification failed", receivedNonce = toHex(res),
localNonce = toHex(localNonce) localNonce = toHex(localNonce)
raise newException(CatchableError, "Nonce verification failed")
else: else:
debug "Secure handshake succeeded" debug "Secure handshake succeeded"
method init(p: Secio) {.gcsafe.} = proc handleConn(s: Secio, conn: Connection): Future[Connection] {.async.} =
var sconn = await s.handshake(conn)
proc writeHandler(data: seq[byte]) {.async, gcsafe.} =
await sconn.writeMessage(data)
var stream = newBufferStream(writeHandler)
result = newConnection(stream)
while not conn.closed:
let msg = await sconn.readMessage()
await stream.pushTo(msg)
method init(s: Secio) {.gcsafe.} =
proc handle(conn: Connection, proto: string) {.async, gcsafe.} = proc handle(conn: Connection, proto: string) {.async, gcsafe.} =
echo "HERE" asyncCheck s.handleConn(conn)
p.codec = SecioCodec s.codec = SecioCodec
p.handler = handle s.handler = handle
method secure*(p: Secio, conn: Connection): Future[Connection] {.async, gcsafe.} = method secure*(s: Secio, conn: Connection): Future[Connection] {.gcsafe.} =
await p.handshake(conn) result = s.handleConn(conn)
proc newSecio*(localPrivateKey: PrivateKey): Secio = proc newSecio*(localPrivateKey: PrivateKey): Secio =
new result new result