Hi,

There's no off-the-shelf solution for this, but you could build something
on top of what exists.

The most obvious approach would be to create a Cap'n Proto interface which
represents a byte stream, like:

    interface ByteStream {
      write @0 (chunk :Data);
      end @1 ();  # indicates EOF
    }

A and C could exchange ByteStreams representing the two directions of a
two-way connection. Then, they could set up a TLS session on top of these,
and create another two-party RPC connection on top of that. So now you have
Cap'n Proto over TLS over Cap'n Proto.

This approach is a bit ugly in that it layers a datagram stream on top of a
byte stream on top of a datagram stream on top of a byte stream. It would
be somewhat cleaner and more performant to create a Cap'n Proto interface
that represents an encrypted message stream, such that each encrypted
message is sent as a single lower-layer RPC call. However, this means
straying away from TLS, which of course brings a big risk of getting the
crypto wrong, so is probably a Bad Idea. That said, it might look something
like:

    interface EncryptedMessageStream {
      # A one-way stream of encrypted messages. A secret key must have been
agreed upon
      # in advance.
      # WARNING: FOR ILLUSTRATIVE PURPOSES ONLY. HAS NOT BEEN REVIEWED FOR
      # CRYPTOGRAPHIC SAFETY. DO NOT USE WITHOUT EXPERT REVIEW.

      send @0 (message :Data);
      # Sends a message encrypted with libsodium's crypto_secretbox(). The
nonce is zero for the
      # first message and increments on each subsequent message.

      end @1 ();  # indicates EOF
    }

    interface EncryptedSessionServer {
      # Interface used to start an ecrypted session.
      # WARNING: FOR ILLUSTRATIVE PURPOSES ONLY. HAS NOT BEEN REVIEWED FOR
      # CRYPTOGRAPHIC SAFETY. DO NOT USE WITHOUT EXPERT REVIEW.

      startSession @0 (clientPk :Data, downstream :EncryptedMessageStream)
          -> (signedServerPk :Data, upstream :EncryptedMessageStream);
      # Start an encrypted session.
      #
      # `upstream` and `downstream` represent the two directions of the
connection.
      #
      # Each side generates a single-use X25519 keypair for the purpose of
key exchange
      # for this session. `clientPk` is the client's X25519 public session
key.
      # `serverPk` is the server's X25519 public session key, signed by the
server's long-term
      # Ed25519 key using libsodium's `crypto_sign()`. The client verifies
the signature to
      # ensure they are talking to the expected server.
      #
      # Both sides can derive session keys using
`crypto_kx_{server,client}_session_keys()`.
    }

In this case you'd write a custom VatNetwork implementation similar to
TwoPartyVatNetwork except that it receives and transmits messages via this
RPC interface rather than from a byte stream.

-Kenton

On Mon, Dec 31, 2018 at 3:13 PM valris <[email protected]> wrote:

> Hey,
>
> is there any possibility to implement two layer tls in capnproto? Suppose
> I have the participants A,B,C with connection like a two party network, but
> B is a proxy. A<->B<->C.
> I want to communicate from A to C with C's public key and wrap that in a
> additional encryption to B, so B only knows metadata of A to C.
>
> If I'm using the tls wrapping functionality of cap'n proto twice, will I
> get a two layer encryption?
> Are there alternatives in the capn' proto library if this isn't the case?
>
> Cheers
>
> --
> You received this message because you are subscribed to the Google Groups
> "Cap'n Proto" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> Visit this group at https://groups.google.com/group/capnproto.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
Visit this group at https://groups.google.com/group/capnproto.

Reply via email to