mirror of
https://github.com/vacp2p/nim-libp2p.git
synced 2026-01-09 14:28:11 -05:00
Compare commits
3 Commits
v1.4.0
...
fixplainte
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a797b5e408 | ||
|
|
56b284a964 | ||
|
|
1d17859eeb |
@@ -26,7 +26,7 @@ import
|
||||
switch, peerid, peerinfo, stream/connection, multiaddress,
|
||||
crypto/crypto, transports/[transport, tcptransport],
|
||||
muxers/[muxer, mplex/mplex, yamux/yamux],
|
||||
protocols/[identify, secure/secure, secure/noise, rendezvous],
|
||||
protocols/[identify, secure/secure, secure/noise, secure/plaintext, rendezvous],
|
||||
protocols/connectivity/[autonat, relay/relay, relay/client, relay/rtransport],
|
||||
connmanager, upgrademngrs/muxedupgrade,
|
||||
nameresolving/nameresolver,
|
||||
@@ -40,6 +40,7 @@ type
|
||||
|
||||
SecureProtocol* {.pure.} = enum
|
||||
Noise,
|
||||
PlainText,
|
||||
Secio {.deprecated.}
|
||||
|
||||
SwitchBuilder* = ref object
|
||||
@@ -134,6 +135,11 @@ proc withNoise*(b: SwitchBuilder): SwitchBuilder {.public.} =
|
||||
b.secureManagers.add(SecureProtocol.Noise)
|
||||
b
|
||||
|
||||
proc withPlainText*(b: SwitchBuilder): SwitchBuilder {.public.} =
|
||||
warn "Using plain text encryption!"
|
||||
b.secureManagers.add(SecureProtocol.PlainText)
|
||||
b
|
||||
|
||||
proc withTransport*(b: SwitchBuilder, prov: TransportProvider): SwitchBuilder {.public.} =
|
||||
## Use a custom transport
|
||||
runnableExamples:
|
||||
@@ -209,8 +215,13 @@ proc build*(b: SwitchBuilder): Switch
|
||||
let
|
||||
seckey = b.privKey.get(otherwise = pkRes.expect("Expected default Private Key"))
|
||||
|
||||
if b.secureManagers.len == 0:
|
||||
b.secureManagers &= SecureProtocol.Noise
|
||||
|
||||
var
|
||||
secureManagerInstances: seq[Secure]
|
||||
if SecureProtocol.PlainText in b.secureManagers:
|
||||
secureManagerInstances.add(PlainText.new(seckey))
|
||||
if SecureProtocol.Noise in b.secureManagers:
|
||||
secureManagerInstances.add(Noise.new(b.rng, seckey).Secure)
|
||||
|
||||
@@ -234,9 +245,6 @@ proc build*(b: SwitchBuilder): Switch
|
||||
transports.add(tProvider(muxedUpgrade))
|
||||
transports
|
||||
|
||||
if b.secureManagers.len == 0:
|
||||
b.secureManagers &= SecureProtocol.Noise
|
||||
|
||||
if isNil(b.rng):
|
||||
b.rng = newRng()
|
||||
|
||||
|
||||
@@ -15,20 +15,57 @@ else:
|
||||
import chronos
|
||||
import secure, ../../stream/connection
|
||||
|
||||
const PlainTextCodec* = "/plaintext/1.0.0"
|
||||
const PlainTextCodec* = "/plaintext/2.0.0"
|
||||
|
||||
type
|
||||
PlainText* = ref object of Secure
|
||||
localPublicKey: PublicKey
|
||||
|
||||
method init(p: PlainText) {.gcsafe.} =
|
||||
proc handle(conn: Connection, proto: string)
|
||||
{.async, gcsafe.} = discard
|
||||
## plain text doesn't do anything
|
||||
PlainTextError* = object of LPError
|
||||
|
||||
PlainTextConnection* = ref object of SecureConn
|
||||
|
||||
method readMessage*(sconn: PlainTextConnection): Future[seq[byte]] {.async.} =
|
||||
var buffer: array[32768, byte]
|
||||
let length = await sconn.stream.readOnce(addr buffer[0], buffer.len)
|
||||
return @(buffer[0 ..< length])
|
||||
|
||||
method write*(sconn: PlainTextConnection, message: seq[byte]): Future[void] =
|
||||
sconn.stream.write(message)
|
||||
|
||||
method handshake*(p: PlainText, conn: Connection, initiator: bool, peerId: Opt[PeerId]): Future[SecureConn] {.async.} =
|
||||
var exchange = initProtoBuffer()
|
||||
exchange.write(2, p.localPublicKey)
|
||||
|
||||
await conn.writeLp(exchange.buffer)
|
||||
let
|
||||
remoteData = await conn.readLp(1024)
|
||||
remotePb = initProtoBuffer(remoteData)
|
||||
var remotePk: PublicKey
|
||||
remotePb.getRequiredField(2, remotePk).tryGet()
|
||||
|
||||
let remotePeerId = PeerId.init(remotePk).valueOr:
|
||||
raise newException(PlainTextError, "Invalid remote peer id: " & $error)
|
||||
|
||||
if peerId.isSome:
|
||||
if peerId.get() != remotePeerId:
|
||||
raise newException(PlainTextError, "Plain text handshake, peer id don't match! " & $remotePeerId & " != " & $peerId)
|
||||
|
||||
var res = PlainTextConnection.new(conn, conn.peerId, conn.observedAddr)
|
||||
return res
|
||||
|
||||
method init*(p: PlainText) {.gcsafe.} =
|
||||
procCall Secure(p).init()
|
||||
p.codec = PlainTextCodec
|
||||
p.handler = handle
|
||||
|
||||
proc new*(T: typedesc[PlainText]): T =
|
||||
let plainText = T()
|
||||
proc new*(
|
||||
T: typedesc[PlainText],
|
||||
privateKey: PrivateKey
|
||||
): T =
|
||||
|
||||
let pk = privateKey.getPublicKey()
|
||||
.expect("Expected valid Private Key")
|
||||
|
||||
let plainText = T(localPublicKey: pk)
|
||||
plainText.init()
|
||||
plainText
|
||||
|
||||
@@ -32,6 +32,7 @@ import testtcptransport,
|
||||
testconnmngr,
|
||||
testswitch,
|
||||
testnoise,
|
||||
testplaintext,
|
||||
testpeerinfo,
|
||||
testpeerstore,
|
||||
testping,
|
||||
|
||||
111
tests/testplaintext.nim
Normal file
111
tests/testplaintext.nim
Normal file
@@ -0,0 +1,111 @@
|
||||
# Nim-LibP2P
|
||||
# Copyright (c) 2022 Status Research & Development GmbH
|
||||
# Licensed under either of
|
||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
||||
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
||||
# at your option.
|
||||
# This file may not be copied, modified, or distributed except according to
|
||||
# those terms.
|
||||
|
||||
{.used.}
|
||||
|
||||
import tables
|
||||
import chronos, stew/byteutils
|
||||
import chronicles
|
||||
import ../libp2p/[switch,
|
||||
errors,
|
||||
multistream,
|
||||
stream/bufferstream,
|
||||
protocols/identify,
|
||||
stream/connection,
|
||||
transports/transport,
|
||||
transports/tcptransport,
|
||||
multiaddress,
|
||||
peerinfo,
|
||||
crypto/crypto,
|
||||
protocols/protocol,
|
||||
muxers/muxer,
|
||||
muxers/mplex/mplex,
|
||||
protocols/secure/plaintext,
|
||||
protocols/secure/secure,
|
||||
upgrademngrs/muxedupgrade,
|
||||
connmanager]
|
||||
import ./helpers
|
||||
|
||||
suite "Plain text":
|
||||
teardown:
|
||||
checkTrackers()
|
||||
|
||||
asyncTest "e2e: handle write & read":
|
||||
let
|
||||
server = @[MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet()]
|
||||
serverPrivKey = PrivateKey.random(ECDSA, rng[]).get()
|
||||
serverInfo = PeerInfo.new(serverPrivKey, server)
|
||||
serverPlainText = PlainText.new(serverPrivKey)
|
||||
|
||||
let transport1: TcpTransport = TcpTransport.new(upgrade = Upgrade())
|
||||
await transport1.start(server)
|
||||
|
||||
proc acceptHandler() {.async.} =
|
||||
let conn = await transport1.accept()
|
||||
let sconn = await serverPlainText.secure(conn, false, Opt.none(PeerId))
|
||||
try:
|
||||
await sconn.writeLp("Hello 1!")
|
||||
await sconn.writeLp("Hello 2!")
|
||||
finally:
|
||||
await sconn.close()
|
||||
await conn.close()
|
||||
|
||||
let
|
||||
acceptFut = acceptHandler()
|
||||
transport2: TcpTransport = TcpTransport.new(upgrade = Upgrade())
|
||||
clientPrivKey = PrivateKey.random(ECDSA, rng[]).get()
|
||||
clientInfo = PeerInfo.new(clientPrivKey, transport1.addrs)
|
||||
clientPlainText = PlainText.new(clientPrivKey)
|
||||
conn = await transport2.dial(transport1.addrs[0])
|
||||
|
||||
let sconn = await clientPlainText.secure(conn, true, Opt.some(serverInfo.peerId))
|
||||
|
||||
discard await sconn.readLp(100)
|
||||
var msg = await sconn.readLp(100)
|
||||
|
||||
await sconn.close()
|
||||
await conn.close()
|
||||
await acceptFut
|
||||
await transport1.stop()
|
||||
await transport2.stop()
|
||||
|
||||
check string.fromBytes(msg) == "Hello 2!"
|
||||
|
||||
asyncTest "e2e: wrong peerid":
|
||||
let
|
||||
server = @[MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet()]
|
||||
serverPrivKey = PrivateKey.random(ECDSA, rng[]).get()
|
||||
serverInfo = PeerInfo.new(serverPrivKey, server)
|
||||
serverPlainText = PlainText.new(serverPrivKey)
|
||||
|
||||
let transport1: TcpTransport = TcpTransport.new(upgrade = Upgrade())
|
||||
await transport1.start(server)
|
||||
|
||||
proc acceptHandler() {.async.} =
|
||||
let conn = await transport1.accept()
|
||||
try:
|
||||
discard await serverPlainText.secure(conn, false, Opt.none(PeerId))
|
||||
finally:
|
||||
await conn.close()
|
||||
|
||||
let
|
||||
acceptFut = acceptHandler()
|
||||
transport2: TcpTransport = TcpTransport.new(upgrade = Upgrade())
|
||||
clientPrivKey = PrivateKey.random(ECDSA, rng[]).get()
|
||||
clientInfo = PeerInfo.new(clientPrivKey, transport1.addrs)
|
||||
clientPlainText = PlainText.new(clientPrivKey)
|
||||
conn = await transport2.dial(transport1.addrs[0])
|
||||
|
||||
expect(CatchableError):
|
||||
discard await clientPlainText.secure(conn, true, Opt.some(clientInfo.peerId))
|
||||
|
||||
await conn.close()
|
||||
await acceptFut
|
||||
await transport1.stop()
|
||||
await transport2.stop()
|
||||
@@ -77,6 +77,46 @@ suite "Switch":
|
||||
check not switch1.isConnected(switch2.peerInfo.peerId)
|
||||
check not switch2.isConnected(switch1.peerInfo.peerId)
|
||||
|
||||
asyncTest "e2e plaintext encryption":
|
||||
let done = newFuture[void]()
|
||||
proc handle(conn: Connection, proto: string) {.async, gcsafe.} =
|
||||
try:
|
||||
let msg = string.fromBytes(await conn.readLp(1024))
|
||||
check "Hello!" == msg
|
||||
await conn.writeLp("Hello!")
|
||||
finally:
|
||||
await conn.close()
|
||||
done.complete()
|
||||
|
||||
let testProto = new TestProto
|
||||
testProto.codec = TestCodec
|
||||
testProto.handler = handle
|
||||
|
||||
let switch1 = newStandardSwitch(secureManagers=[PlainText])
|
||||
switch1.mount(testProto)
|
||||
|
||||
let switch2 = newStandardSwitch(secureManagers=[PlainText])
|
||||
await switch1.start()
|
||||
await switch2.start()
|
||||
|
||||
let conn = await switch2.dial(switch1.peerInfo.peerId, switch1.peerInfo.addrs, TestCodec)
|
||||
|
||||
check switch1.isConnected(switch2.peerInfo.peerId)
|
||||
check switch2.isConnected(switch1.peerInfo.peerId)
|
||||
|
||||
await conn.writeLp("Hello!")
|
||||
let msg = string.fromBytes(await conn.readLp(1024))
|
||||
check "Hello!" == msg
|
||||
await conn.close()
|
||||
|
||||
await allFuturesThrowing(
|
||||
done.wait(5.seconds),
|
||||
switch1.stop(),
|
||||
switch2.stop())
|
||||
|
||||
check not switch1.isConnected(switch2.peerInfo.peerId)
|
||||
check not switch2.isConnected(switch1.peerInfo.peerId)
|
||||
|
||||
asyncTest "e2e use switch dial proto string with custom matcher":
|
||||
let done = newFuture[void]()
|
||||
proc handle(conn: Connection, proto: string) {.async, gcsafe.} =
|
||||
|
||||
Reference in New Issue
Block a user