Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

MLAPI.Cryptography - Easy cryptography for game networking

Discussion in 'Netcode for GameObjects' started by TwoTen, Jun 11, 2019.

  1. TwoTen


    May 25, 2016
    Doing cryptographic work in any languages with access to the .NET framework can be a breeze, in Unity's Mono version, not so much. It's missing critical things such as BigInt, ECDH-E and more. To address this, the MLAPI created it's own ECDH-E implementation a while back. I have now decided to break this out into it's own lib which is super easy to use.

    It's all open source, available on GitHub

    It has a BigInt and EllipticCurve implementation for the DIY folks, and a super easy API for the people that want easy cryptography.

    This includes a DiffieHellman implementation and a abstracted version that includes signed handshakes to prevent MITM attacks. Here is an example of how to use the signed version (The non signed is even easier to use, 3 lines per side, see the readme for instructions).

    Code (CSharp):
    2. // Key pairs
    3. RSAParameters privateKey;
    4. RSAParameters publicKey;
    6. // Generate keys, you can use X509Certificate2 instead of raw RSA keys.
    7. using (RSACryptoServiceProvider rsaGen = new RSACryptoServiceProvider(2048))
    8. {
    9.     privateKey = rsaGen.ExportParameters(true);
    10.     publicKey = rsaGen.ExportParameters(false);
    11. }
    13. using (RSACryptoServiceProvider serverRSA = new RSACryptoServiceProvider())
    14. using (RSACryptoServiceProvider clientRSA = new RSACryptoServiceProvider())
    15. {
    16.     serverRSA.ImportParameters(privateKey);
    17.     clientRSA.ImportParameters(publicKey);
    19.     // Both create their instances, constructor can take certificate instead or RSA key.
    20.     ECDiffieHellmanRSA serverDiffie = new ECDiffieHellmanRSA(serverRSA);
    21.     ECDiffieHellmanRSA clientDiffie = new ECDiffieHellmanRSA(clientRSA);
    23.     // Exchange publics
    25.     /* START TRANSMISSION */
    26.     byte[] serverPublic = serverDiffie.GetSecurePublicPart();
    27.     byte[] clientPublic = clientDiffie.GetSecurePublicPart();
    28.     /* END TRANSMISSION */
    30.     // Calculate shared
    31.     byte[] key1 = serverDiffie.GetVerifiedSharedPart(clientPublic);
    32.     byte[] key2 = clientDiffie.GetVerifiedSharedPart(serverPublic);
    33. }

    The above code, running both parts of the signed exchange with 2048 bit RSA keys takes ~70 milliseconds on my i7 7700k @4.2GHz, it's pretty fast.
    Last edited: Jun 12, 2019
    MadMojo and MurphyMurph_21 like this.
  2. maxhapeyenka


    Mar 12, 2023
    Awesome, thanks!
    I see with this library client and server can come up with a shared key, but how can this key be used to encrypt data?

    Would be awesome to see Encrypt(string)/Decrypt(string) methods as well.
    Last edited: Dec 15, 2023