Lazy encryption in NWListener

Hi, I'd like to lazily enable encryption on my NWListener. Basically, right now, I've implemented encryption in the NWListener's initialization phase, like so:

import CryptoKit
import Network

extension NWParameters {
    // Create parameters for use with Connection and Listener.
    convenience init(secret: String, identity: String) {

        let tcpOptions = NWProtocolTCP.Options()
        tcpOptions.enableKeepalive = true
        tcpOptions.keepaliveIdle = 2

        let tlsOptions = NWProtocolTLS.Options()

        let authenticationKey = SymmetricKey(data: secret.data(using: .utf8)!)

        var authenticationCode = HMAC<SHA256>.authenticationCode(for: identity.data(using: .utf8)!, using: authenticationKey)

        let authenticationDispatchData = withUnsafeBytes(of: &authenticationCode) { (ptr: UnsafeRawBufferPointer) in
            DispatchData(bytes: ptr)
        }

        let psk = authenticationDispatchData as __DispatchData

        var identityData = identity.data(using: .unicode)!
        let identityDispatchData = withUnsafeBytes(of: &identityData) { (ptr: UnsafeRawBufferPointer) in
            DispatchData(bytes: ptr)
        }

        let psk_identity = identityDispatchData as __DispatchData

        sec_protocol_options_add_pre_shared_key(
        tlsOptions.securityProtocolOptions, psk, psk_identity
)

        let ciphersuite = tls_ciphersuite_t(rawValue: TLS_PSK_WITH_AES_128_GCM_SHA256)!       sec_protocol_options_append_tls_ciphersuite(
tlsOptions.securityProtocolOptions, ciphersuite
)

        self.init(tls: tlsOptions, tcp: tcpOptions)

        self.includePeerToPeer = true

        let customProtocol = NWProtocolFramer.Options(definition: TLVMessageProtocol.definition)
      self.defaultProtocolStack.applicationProtocols.insert(customProtocol, at: 0)
    }
}

The preshared key (secret) would be a combination of the user's and a peer's CLBeacon major/minor. However, I want to be able to create an NWListener before detecting a peer's CLBeacon, since it's quite a heavy and time-consuming operation.

Is there a way to create an NWListener first, and then give it the encryption / preshared key later?

Is there a way to create an NWListener first, and then give it the encryption / preshared key later?

No, any listener configured to serve TLS connections will need to be setup to do so up front and cannot be upgraded. This does not mean that a clean text listener cannot also be setup on a different port. Having said that I would absolutely avoid negotiating any sort of SymmetricKey in the clear as others on your network will be able to eavesdrop on this traffic.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

I see. Implementing this kind of lazy encryption myself would exponentially increase complexity, and I'm not sure it's worth it. I'm using the Network framework for two-device peer-to-peer connectivity since I've been advised to stay away from Multipeer Connectivity. However, it seems like Multipeer Connectivity implements its own encryption and all I need to do is specify .required in the argument.

My needs are quite simple – only two devices need to share a peer-to-peer connection, and only an image and some text being is sent over that connection. But encryption is a must. Do you think Multipeer Connectivity may be a better fit for my needs?

Do you think Multipeer Connectivity may be a better fit for my needs?

No.

Regarding:

My needs are quite simple – only two devices need to share a peer-to-peer connection, and only an image and some text being is sent over that connection. But encryption is a must.

I think it's excellent you are encrypting your TLS connection. You will need to find a way to negotiate the key with your device or your server before setting up the listener. One way to do this, if you have physical access to the device, is to pass they key data over QR code. I created an example of how to do this here. Now, this is just one example, but there are several other key negotiation techniques out there you can use.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

No.

Could you expand on this a little bit? I’ve seen mixed thoughts online about Multipeer Connectivity, and would love to hear yours.

Unfortunately, I won’t have physical access to the other device - this is going to be a proximity-based data transfer, kind of like NFC (which I can’t use for various reasons). That’s why I’m using CLBeacon - each phone acts as an iBeacon advertiser and an iBeacon detector, and when it finds a beacon in its immediate proximity, tries to initiate a peer-to-peer connection with them using Network.framework.

Maybe the key negotiation could happen during that iBeacon detection phase, where if it detects an iBeacon, it sends it a UInt64 over Bluetooth and receives another UInt64, and then both peers combine them to create the key. Problem is, anyone could just eavesdrop eavesdrop on the Bluetooth connection and gain access to the key. Is there some other form of key negotiation I could do during the iBeacon phase?

Could you expand on this a little bit? I’ve seen mixed thoughts online about Multipeer Connectivity, and would love to hear yours.

Sure. My thoughts on Multipeer generally line up with what Quinn has described on this thread. Multipeer is useful when a small handful of peers need to transmit data back and forth between each other acting as a client and a server. For example each peer can send and receive with the same API instead of setting up a NWListener and a NWConnection. This is great for a small set of peers, while network connectivity is working well, and for the transmission small amounts of data. This quickly breaks down if one of the peers in your network is having network issues or is indirectly connected to a peer through another peer's connection. Then the state becomes hard to track and the user is left wonder why they cannot reach another peer.

Regarding:

Is there some other form of key negotiation I could do during the iBeacon phase?

This would be a question to bring up on on the Bluetooth tags, i.e. Core Bluetooth or IOBluetooth.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Lazy encryption in NWListener
 
 
Q