Closed paulpach closed 2 years ago
Better than adding a TLS transport is to implement transport agnostic protocol encryption. That will run on all platforms. If you are willing to add an extra handshake, I can happily help with implementing the crypto side of things with a proper ECDHE key exchange.
Encrypting every single message would be an overkill, adding a way to encrypt just some messages would be the best option.
Encrypting every single message would be an overkill, adding a way to encrypt just some messages would be the best option.
Depends, if you go with a stream cipher like ChaCha20 and Poly1305 for authentication it's actually not overkill at all. If you want to go down the blockcipher route with AES and SHA for the HMAC, then it will probably be quite overkill. A per message encryption & authentication is prefered imho. (Even for AES-CTR I would not want it on every message)
That's why I don't suggest using a TLS transport.
Here is an example in how it is done in cough:
InvokeRpc(RpcMethod, SecurityFlags.Encrypt);
InvokeRpc(RpcMethod, SecurityFlags.Encrypt | SecurityFlags.Authenticate);
InvokeRpc(RpcMethod, SecurityFlags.Authenticate);
But honestly, this is much more a question for the head maintainers where they want to take the project. If they are fine with depending on BouncyCastle for example, then it will be a breeze.
What's speaking against using (D)TLS and just encrypting everything? Surely the overhead is neglectable
(I'm not an expert on this, so if this is wrong please do enlighten me)
What's speaking against using (D)TLS and just encrypting everything? Surely the overhead is neglectable
(I'm not an expert on this, so if this is wrong please do enlighten me)
What's speaking against it is that there is no benefit to being TLS compliant.
TLS is built into .NET but it's not well ported to all platforms, and since we are in a closed protocol there is 0 benefit to being TLS compliant. You are just increasing development time by many times and are increasing the handshake process.
What I did In my personal projects is that I wrote a ECDHE implementation in C#, used BouncyCastle's BigInt (you can use the .NET one tho), and then .NET's AES & HMAC.
My implementation of ECDHE is licenced under MIT so it could be snagged straight off. It's very performant.
But .Net already has ECDHE, doesn't it?
But .Net already has ECDHE, doesn't it?
Yes, but it's not ported to Mono. That's why we had to write our own.
A generic encryption layer would be cool and all.
But let's focus on MVP (Minimum Viable Product): What is the bare minimun necessary and simplest way to get secure communication?
Simple TLS is better than nothing and relatively trivial to implement, that is where we should start.
Later we can think of a more generic encryption layer that can work with other transports.
A generic encryption layer would be cool and all.
But let's focus on MVP (Minimum Viable Product): What is the bare minimun necessary and simplest way to get secure communication?
Simple TLS is better than nothing and relatively trivial to implement, that is where we should start.
Later we can think of a more generic encryption layer that can work with other transports.
So you want to just wrap Telepathy in TLSStream by .NET and call it the day?
Try it in Unity's Mono version. As you can see by the copyright, it's microsofts implementation.
Pretty much ALL Cryptography Next Generation stuff is not ported. Because it's proprietary since it has a FIPS certification and all of that.
So you want to just wrap Telepathy in TLSStream by .NET and call it the day?
I want to wrap Telepathy in TLSStream and call it a start.
it is all about the Minimal Viable Product
For people looking to do this today -- you could just use TLS termination to stay compatible with mirror and then proceed to use a service in the middle that knows how to talk it.
For people looking to do this today -- you could just use TLS termination to stay compatible with mirror and then proceed to use a service in the middle that knows how to talk it.
If you are not session identified you are still vulnerable to MITM attacks, even if you use a secure side channel.
Excuse the ignorance, I'm new to Mirror and my main focus is not cryptography and security, so if you can break it down that's be great.
Assuming a secure origin proxy in front of an application server running Mirror that terminates to the the application server / game server, what is the hypothetical attack that enables a MITM?
Excuse the ignorance, I'm new to Mirror and my main focus is not cryptography and security, so if you can break it down that's be great.
Assuming a secure origin proxy in front of an application server running Mirror that terminates to the the application server / game server, what is the hypothetical attack that enables a MITM?
Alice is the server, Bob is the connecting client. Authy is like a secure web server. Mallory is between Alice and Bob.
Bob connects to Alice, Mallory allows this. Bob then sends Authy a message saying "tell Alice that the game connection x.y.z is me!". Now you have done secure authentication. Mallory never got to see that token, but he still has escalated privileges because he can still intercept the game server messages. This is unless you treat them as separate entitys completley and never combine the two, in which case you have just made your life hell and are running two game servers to avoid rather than fixing the problem.
The truth here is that implementing a TLSStream is fairly easy (given there is support or that the Mirror project is fine in having BouncyCastle as a dep), and even protocol stuff is not all too time-consuming, I remain my offer to support the implementation of it. Especially now that I see people actually launching games and actually sending unencrypted data. It's a responsibility of the library in my eyes.
But then again, the views of Mirror is for everything to be REALLY easy to use. One I don't always agree with but certainly, one that I can respect. The reality is that when implementing encryption you ARE making it more difficult for end users. They have to manage certificates for their dedicated servers or have secured messaging relays of hosts. But it can certainly be made easier with good documentation.
For my personal projects for example, I wrote a certificate generator that issues a CA cert and then self signs a certificate and prints instructions. This makes it dead simple to get started with encryption.
You can see that here (Tell me if that link is not allowed) It's all open source.
Basically makes certificate handling a copy and paste matter, and you only have to update a text field on the server for production, for development we just have to manually trust our CA.
Oh, and btw, I started working on a transport adapter with encryption and it works fine. I just used the ECDHE implementation from my personal projects, BigInt from Bouncy and it works. (Note that I only spent like 2 hours writing it so it's dirty af), but it shows that this isn't a rocket science project. It can be done in very little time with a so-called "MVP". If you want integration to the lib tho, and not just have every message sent you might need more work. Right now I just used a hack where I used channel based encryption & authentication.
So you basically make this crypto transport your main, then you can plop another transport into it (for example multiplexer), and then add your final transports there. Like a chain. Not pretty but works.
@TwoTenPvP that sounds good. And yes, the chained transport is exactly how I envisioned this.
Any chance you can send a Pull request for that?
Making it optional (so you can pick if you want a message encrypted or not) is trivial:
have 2 channels, one encrypted one non encrypted. the non encrypted channel would just be a passthrough to the underlying channel.
@TwoTenPvP that sounds good. And yes, the chained transport is exactly how I envisioned this.
Any chance you can send a Pull request for that?
Making it optional (so you can pick if you want a message encrypted or not) is trivial: have 2 channels, one encrypted one non encrypted. the non encrypted channel would just be a passthrough to the underlying channel.
If you want it in the main repo, maybe. I will still have to clean it up. I am building it to conform to the MLAPI's validation system, which means that Mirror will be able to use MLAPI's tools to generate developer certificates and such super easily. I might be able to get it all completed during this weekend. I have a ton of new tooling for this purpose, thus it would be of great benefit to Mirror users to be able to use my cert generators and such to make certificate management a breeze. Everything is open sourced.
It's really up to you guys if you are fine with Bouncy's BigInt implementation being in your main repo and also our ECDHE implementation. If not I can do it as a standalone transport that users can download as a DLL.
As for making it optional, it sure is. But it's super limited rn due to the fact that it's a big hack. For example, we need to send authentication messages on encrypted channels. But I wouldn't say it's "trivial" to be optional. Much more a nice to have. Especially if you go with a fast stream cipher like ChaCha you have nothing to lose really.
Let's start with a separate transport, if there is enough demand for it, we can always merge it in master.
In the same theme, I will make my async based TcpTransport an addon and add support for TLS.
IMHO a transparent ECDHE handshake with each client would be nice, then you would only use it if you need it.
I ended up using RSA/AES because it doubles as a server signature... and because there is no DiffieHellmann implementation "out of the box" on unity, while there is for RSA.
That is just insecure.. There is a reason people use DiffieHellman. And my implementation is open source, no reason not to use it.
@TwoTenPvP if you wish to write a PR, I would definitely take a look.
In my mind, the reasonable way to do it would be to write an EncryptedTransport, which takes another transport and whatever config you need. It would do handshake, encryption and decryption and pass the results to the underlying transport.
It may not need to be merged, it could also live as a standalone transport for mirror.
We will have to implement ssl no matter what for websockets, otherwise webgl does not work in https sites. But we can definitely use what you describe for other transports.
Hello, I am currently looking at the possibility to use a secure connection from mobile app (android and ios) and windows clients (exe and UWP), using IL2cpp build. Is the Websocket Secure transport a valid option? Or is it something that should be used for webgl builds only? Thanks
closing because it's been almost two years. if anyone wants to make an encryped transport then please open a PR :)
Implementing TLS is not so simple because of the self-signed certificate requirement. .NET has not contained the functionality to generate self-signed certificates until quite recently, and that functionality is not available in Unity Mono. This adds an additional dependency on something like Mono.Security just to generate the encryption certs. I have not had much success in using certs generated by Mono.Security in securing telepathy. I just get cryptic error messages about failed handshakes without any further details. I am considering implementing my own Diffie-Hellman key exchange just to be done with it.
@TwoTenPvP do you have a link to your ECDHE implementation?
I honestly don't see why you'd want a fully encrypted transport. If you are doing heavy network I/O, then you'll already probably be stressing out Unity, and then adding the encryption process on top of that stress is likely to cause even more lag/stutters unless it was hardware accelerated.
It's probably better to encrypt the data before you send it over the wire, rather than letting the transport try to encrypt/decrypt the whole packet. In reality, the chances of someone spying on your networked game and sniffing for secrets in the data is low (but not zero). Even then, you shouldn't be putting sensitive stuff in your game anyway, if you're transmitting passwords or whatnot, you should be using some sort of hashing method - not plain text strings.
And if you're looking for a solid crypto implementation, I'd probably recommend using BouncyCastle's C# Crypto library. That is tried and true, used by many systems including Android itself. So go check that out.
@SoftwareGuy sorry you are mistaken about the requirement for encryption. Sending sensitive information is kind of the whole point of the software that I'm working on. Unity is used for more than video games. Encrypting at a higher layer on the networking stack makes no sense either since then I would have to implement encryption everywhere instead of one place, including modifying the Dissonance voice comms library.
I will check out the BouncyCastle C# crypto library, thanks for the tip. I am also planning on contributing back to Mirror once I get an implementation working.
@TwoTenPvP do you have a link to your ECDHE implementation?
EC https://github.com/MidLevel/MLAPI.Cryptography/blob/master/MLAPI.Cryptography/EllipticCurves/EllipticCurve.cs ECDH-E https://github.com/MidLevel/MLAPI.Cryptography/blob/master/MLAPI.Cryptography/KeyExchanges/ECDiffieHellman.cs ECDH-E with certificate https://github.com/MidLevel/MLAPI.Cryptography/blob/master/MLAPI.Cryptography/KeyExchanges/ECDiffieHellmanRSA.cs
Implementing TLS is not so simple because of the self-signed certificate requirement. .NET has not contained the functionality to generate self-signed certificates until quite recently, and that functionality is not available in Unity Mono. This adds an additional dependency on something like Mono.Security just to generate the encryption certs. I have not had much success in using certs generated by Mono.Security in securing telepathy. I just get cryptic error messages about failed handshakes without any further details. I am considering implementing my own Diffie-Hellman key exchange just to be done with it.
Also here is how I created certs: https://github.com/MidLevel/DevelopmentCertificateGenerator
Encryption with TLS and certificates (both signed and self-signed via BouncyCastle) are now implemented in https://github.com/vis2k/Telepathy/pull/96
After this pull request is accepted there will have to be some additional code changes in the Mirror repository to expose the encryption configuration options in the inspector. The code has been tested to work with the self-signed BouncyCastle certificates but not the fully signed version (I don't currently have access to a legitimately signed certificate).
This is being worked on in HushHush.
HushHush will be a middleware transport, meaning it works on top of your existing transport and adds an encryption layer.
HushHush uses industry standard DTLS to encrypt messages before passing it down to the underlying transport.
Closing as Monke Transport was added months ago.
Add an encrypted transport such as TLS 1.3.