Networking - Secure transport within SpiderMonkey

The time has come for me to work on my login server and other systems that require a level of security. To that end I have been looking at the possibility of adding a means to securely send messages between SpiderMonkey’s Client and Server.

The forums show that encryption in SpiderMonkey has come up a few times but I didn’t find any solutions mentioned and the consensus seemed to be do it externally.

Anyway my musing on the topic are below and I would be curious if anyone else has implemented or thought of better/different ways of doing things.

Why not use HTTPS or TLS?

The obvious solution to sending data securely is to use https or tls but I ruled this out because it has outside dependencies and issues that would add complexity and costs.

The general idea

Use an Asymmetric key pair to securely transfer a generated symmetric key from client to server. This symmetric key can can be used to encrypt traffic both ways between client and server. (public key deployed with client and the private key stays on server)

  1. Client connects to server
  2. Client generates new symmetric key and encrypts it using the public key before sending to server.
  3. Server decrypts symmetric key and stores it for use with the HostedConnection. (Seperate key for each HostedConnection)
  4. Any ‘secret’ data can now be encrypted using the symmetric key by Client and Server.

In short the same principle as https but without the accompanying issues.

How can this be implemented so that it works with SpiderMonkey

1.) Per message encryption.

Extend AbstractMessage in a similar way that ZIPCompressedMessage does to create an EncryptedMessage and have a corresponding Serializer to handle these messages. Loosely put, a message that needs to be encrypted is put inside an encrypted message. The Serializer turns the original message into a byte[] which is then encrypted and becomes the content of the EncryptedMessage. The reverse happens at the receiving end.

2.) Implement an encrypted channel (While at it could also implement a compressed channel as well)

If you can add a channel that automatically encrypts and decrypts upon sending and receiving it would eliminate the messy nature and potential bottlenecks of option one. On a separate channel the encryption/decryption process would not slow down any time sensitive packets. Eliminating the requirement of wrapping messages would also make it a cleaner solution if there is a lot of encrypted messages in use.

Looking at SpiderMonkey source I could not find an easy way to introduce an encrypted channel to DefaultServer and DefaultClient without significant source changes or rolling a new Implementations and supporting classes.

1 Like

You probably mean “SpiderMonkey over SSL”… why bother with http when there’s no “hypertext” involved?

Your right but it depends on what you are doing. I was thinking too much about my use case when I wrote the post.

I plan to have a small HTTPS site that users can login to for profile changes and account info type stuff and I got to thinking what if I could use that same webserver to authenticate against.

Sure you can (and should) use that same server to authenticate against… but you don’t need SpiderMonkey for that. That’s a separate regular HTTP connection. I do this in the newer version of Mythruna… make an HTTPS connection to authenticate before communicating with the server. That supplies the client with a temporary token that it gives to the server which also contacts the auth server to verify the token.

As to the other, the networking was designed to support custom kernels and connectors at the architecture level but the outward support in DefaultClient and DefaultServer was never added because no such transports ever materialized in the wild. I think the only code that has to change to support a new one is the channel setup.

Essentially, as you say, you are talking about reinventing SSL. Which is too bad because the only issue I’ve ever had with SSL is in the key/cert configuration. I don’t know what external dependencies it requires as I’ve never needed any other than messing with keytool to setup certificates. It’s possible there is already an easier way to do that at runtime that doesn’t require messing with an on-disk cert registry… I never looked very long.

My approach for authentification is

→ Password is stored with salt as hash in db on server → SHA256

  1. Connection is established by client
  2. Server sends a login request with a Random String
  3. Client hashes entered password with SHA256
  4. Client concates random string to hash of password
  5. Client hashes this again
  6. Client sends hash to server and username in clear text
  7. Based on username server gets the sha256 hashed password.
  8. Server uses the previous send random string concats it and hashes it.
    9 if the client used the same password both hashes now should be equal.

→ Bonus you can easily do like 2k iterations on the hashes.
→ The login itself is kinda secure with this, all other data is of course not secured.

This pretty much is a simpler but practical way of your general approach.

an alternative approach might be to use GPG instead of synchronous systems for this.
Let each Client generate a key on registering, and store the public one on server for comparing.
Client itself then authentificates via the key.
→ SSH public certificate logic might also be used for a similar approach as there are already pure java implementations for server and client in it.

1 Like

Authentication is just one use (the primary requirement for me right now) of the secure channel/message. Eventually I would want to be able to send other secure traffic. Working as a network admin I get rather peeved when devs and users send or store personally identifiable data and other ‘private’ data in the clear. Working with private and protected data at work all day could just be making me overzealous though.

As for SSL the problem is that without verifying the cert through a certificate authority you can’t be sure you are talking to the right host. If you disable the host check within the SSL protocol a malicious host could intercept the traffic and send back a public key that they can decrypt.

If the public key is in the client source there is no need to send it. Of course a malicious entity could modify the source at the client side but if they have that level of control over a pc then the user has a bigger problem to worry about.

Once again though I could just be being overcautious, overzealous or just overcomplicating the process.

@Empire_Phoenix
How did you get the password hash on the server in the first place? If you rely on a external secure website or something then it would be okay. If you sent the hash in clear text it can be intercepted and an attacker can authenticate at will.

If the string is sent in the clear then it too can be intercepted and nullified. Are you using a salt? If so how was that transferred?

As a side note is your implementation vulnerable to timing attacks? Ensuring the method used to compare the two hashes takes the same time return a success or failure message. Timing attacks across a network are not so impractical these days.

Yes, but for example, “out of the box”, Java can connect to HTTPS hosts as long as they have a valid cert through a regular trusted authority that is included in the JRE’s trust store. The thing is that often during development you have self-signed certs and stuff used for testing and it’s a pain to make game developers supply those just to make a channel work. The normal way is by modifying the default keystore or creating a special keystore and pointing to it, etc… In my experience, this has been slightly different on different versions of Java and quite different on different platforms.

…but in theory, I guess SSL connections could be created just fine to hosts with trusted certs… but then the server side needs to know that. Honestly, I don’t know if that’s done at the SSL level or not… I know HTTPS handles it just fine but I don’t know where the automagic happens in Java.

And note: as mentioned in the authentication stuff… nothing stops you from sending private data over an HTTPS connection outside of SpiderMonkey. It’s not like that will be efficient to send no matter how you encrypt it so it’s unlikely to be anything that requires SpiderMonkey’s level of performance.

Initially via a Registration Website that is https only with a actual normal valid certificate. That way most problems are circumvented, and I dont bloat the game core with this.

The whole process for the login is perfectly identicall for both, sucess and non sucess case, the last step is only a String.equals for the hash on the serverside. Currently the largest variance is the Database itself when retrecieving the userdata.

Since I know the username it is also quite simple to just add a linux style increasing cooldown to login attempts from the same location||same username.

Yeah, me too… it was 10000x easier to setup a pay wall on a web site than it would have been to do directly in my game.

Well who says its not directly in game for me?

JavaFx has a chromium based embedded browser :slight_smile: So for the user it just looks like any other ui.

Yeah, but it’s still just a web page. You kind of know what I meant. :wink: