@@ -51,6 +51,10 @@ public bool isHost
51
51
52
52
public NetworkingConfiguration NetworkConfig ;
53
53
54
+ private EllipticDiffieHellman clientDiffieHellman ;
55
+ private Dictionary < int , byte [ ] > diffieHellmanPublicKeys ;
56
+ private byte [ ] clientAesKey ;
57
+
54
58
private void OnValidate ( )
55
59
{
56
60
if ( SpawnablePrefabs != null )
@@ -88,6 +92,7 @@ private ConnectionConfig Init(NetworkingConfiguration netConfig)
88
92
pendingClients = new HashSet < int > ( ) ;
89
93
connectedClients = new Dictionary < int , NetworkedClient > ( ) ;
90
94
messageBuffer = new byte [ NetworkConfig . MessageBufferSize ] ;
95
+ diffieHellmanPublicKeys = new Dictionary < int , byte [ ] > ( ) ;
91
96
MessageManager . channels = new Dictionary < string , int > ( ) ;
92
97
MessageManager . messageTypes = new Dictionary < string , ushort > ( ) ;
93
98
MessageManager . messageCallbacks = new Dictionary < ushort , Dictionary < int , Action < int , byte [ ] > > > ( ) ;
@@ -374,15 +379,29 @@ private void Update()
374
379
}
375
380
else
376
381
{
382
+ byte [ ] diffiePublic = new byte [ 0 ] ;
383
+ if ( NetworkConfig . EnableEncryption )
384
+ {
385
+ clientDiffieHellman = new EllipticDiffieHellman ( EllipticDiffieHellman . DEFAULT_CURVE , EllipticDiffieHellman . DEFAULT_GENERATOR , EllipticDiffieHellman . DEFAULT_ORDER ) ;
386
+ diffiePublic = clientDiffieHellman . GetPublicKey ( ) ;
387
+ }
388
+
377
389
int sizeOfStream = 32 ;
378
390
if ( NetworkConfig . ConnectionApproval )
379
391
sizeOfStream += 2 + NetworkConfig . ConnectionData . Length ;
392
+ if ( NetworkConfig . EnableEncryption )
393
+ sizeOfStream += 2 + diffiePublic . Length ;
380
394
381
395
using ( MemoryStream writeStream = new MemoryStream ( sizeOfStream ) )
382
396
{
383
397
using ( BinaryWriter writer = new BinaryWriter ( writeStream ) )
384
398
{
385
399
writer . Write ( NetworkConfig . GetConfig ( ) ) ;
400
+ if ( NetworkConfig . EnableEncryption )
401
+ {
402
+ writer . Write ( ( ushort ) diffiePublic . Length ) ;
403
+ writer . Write ( diffiePublic ) ;
404
+ }
386
405
if ( NetworkConfig . ConnectionApproval )
387
406
{
388
407
writer . Write ( ( ushort ) NetworkConfig . ConnectionData . Length ) ;
@@ -471,6 +490,14 @@ private void HandleIncomingData(int clientId, byte[] data, int channelId)
471
490
472
491
ushort bytesToRead = reader . ReadUInt16 ( ) ;
473
492
byte [ ] incommingData = reader . ReadBytes ( bytesToRead ) ;
493
+ if ( NetworkConfig . EncryptedChannels . Contains ( channelId ) )
494
+ {
495
+ //Encrypted message
496
+ if ( isServer )
497
+ incommingData = CryptographyHelper . Decrypt ( incommingData , connectedClients [ clientId ] . AesKey ) ;
498
+ else
499
+ incommingData = CryptographyHelper . Decrypt ( incommingData , clientAesKey ) ;
500
+ }
474
501
475
502
if ( isServer && isPassthrough && ! NetworkConfig . RegisteredPassthroughMessageTypes . Contains ( messageType ) )
476
503
{
@@ -555,6 +582,18 @@ private void HandleIncomingData(int clientId, byte[] data, int channelId)
555
582
DisconnectClient ( clientId ) ;
556
583
return ;
557
584
}
585
+ byte [ ] aesKey = new byte [ 0 ] ;
586
+ if ( NetworkConfig . EnableEncryption )
587
+ {
588
+ ushort diffiePublicSize = reader . ReadUInt16 ( ) ;
589
+ byte [ ] diffiePublic = reader . ReadBytes ( diffiePublicSize ) ;
590
+ diffieHellmanPublicKeys . Add ( clientId , diffiePublic ) ;
591
+ /*
592
+ EllipticDiffieHellman diffieHellman = new EllipticDiffieHellman(EllipticDiffieHellman.DEFAULT_CURVE, EllipticDiffieHellman.DEFAULT_GENERATOR, EllipticDiffieHellman.DEFAULT_ORDER);
593
+ aesKey = diffieHellman.GetSharedSecret(diffiePublic);
594
+ */
595
+
596
+ }
558
597
if ( NetworkConfig . ConnectionApproval )
559
598
{
560
599
ushort bufferSize = messageReader . ReadUInt16 ( ) ;
@@ -583,6 +622,12 @@ private void HandleIncomingData(int clientId, byte[] data, int channelId)
583
622
sceneIndex = messageReader . ReadUInt32 ( ) ;
584
623
}
585
624
625
+ if ( NetworkConfig . EnableEncryption )
626
+ {
627
+ ushort keyLength = reader . ReadUInt16 ( ) ;
628
+ clientAesKey = clientDiffieHellman . GetSharedSecret ( reader . ReadBytes ( keyLength ) ) ;
629
+ }
630
+
586
631
float netTime = messageReader . ReadSingle ( ) ;
587
632
int remoteStamp = messageReader . ReadInt32 ( ) ;
588
633
int msDelay = NetworkTransport . GetRemoteDelayTimeMS ( hostId , clientId , remoteStamp , out error ) ;
@@ -901,8 +946,18 @@ internal void PassthroughSend(int targetId, int sourceId, ushort messageType, in
901
946
writer . Write ( orderId . Value ) ;
902
947
writer . Write ( true ) ;
903
948
writer . Write ( sourceId ) ;
904
- writer . Write ( ( ushort ) data . Length ) ;
905
- writer . Write ( data ) ;
949
+ if ( NetworkConfig . EncryptedChannels . Contains ( channelId ) )
950
+ {
951
+ //Encrypted message
952
+ byte [ ] encrypted = CryptographyHelper . Encrypt ( data , connectedClients [ targetId ] . AesKey ) ;
953
+ writer . Write ( ( ushort ) encrypted . Length ) ;
954
+ writer . Write ( encrypted ) ;
955
+ }
956
+ else
957
+ {
958
+ writer . Write ( ( ushort ) data . Length ) ;
959
+ writer . Write ( data ) ;
960
+ }
906
961
}
907
962
NetworkTransport . QueueMessageForSending ( hostId , targetId , channelId , stream . GetBuffer ( ) , sizeOfStream , out error ) ;
908
963
}
@@ -951,8 +1006,25 @@ internal void Send(int clientId, string messageType, string channelName, byte[]
951
1006
writer . Write ( isPassthrough ) ;
952
1007
if ( isPassthrough )
953
1008
writer . Write ( clientId ) ;
954
- writer . Write ( ( ushort ) data . Length ) ;
955
- writer . Write ( data ) ;
1009
+
1010
+ if ( NetworkConfig . EncryptedChannels . Contains ( MessageManager . channels [ channelName ] ) )
1011
+ {
1012
+ //This is an encrypted message.
1013
+ byte [ ] encrypted ;
1014
+ if ( isServer )
1015
+ encrypted = CryptographyHelper . Encrypt ( data , connectedClients [ clientId ] . AesKey ) ;
1016
+ else
1017
+ encrypted = CryptographyHelper . Encrypt ( data , clientAesKey ) ;
1018
+
1019
+ writer . Write ( ( ushort ) encrypted . Length ) ;
1020
+ writer . Write ( encrypted ) ;
1021
+ }
1022
+ else
1023
+ {
1024
+ //Send in plaintext.
1025
+ writer . Write ( ( ushort ) data . Length ) ;
1026
+ writer . Write ( data ) ;
1027
+ }
956
1028
}
957
1029
if ( isPassthrough )
958
1030
clientId = serverClientId ;
@@ -965,7 +1037,12 @@ internal void Send(int clientId, string messageType, string channelName, byte[]
965
1037
966
1038
internal void Send ( int [ ] clientIds , string messageType , string channelName , byte [ ] data , uint ? networkId = null , ushort ? orderId = null )
967
1039
{
968
- int sizeOfStream = 6 ;
1040
+ if ( NetworkConfig . EncryptedChannels . Contains ( MessageManager . channels [ channelName ] ) )
1041
+ {
1042
+ Debug . LogWarning ( "MLAPI: Cannot send messages over encrypted channel to multiple clients." ) ;
1043
+ return ;
1044
+ }
1045
+ int sizeOfStream = 6 ;
969
1046
if ( networkId != null )
970
1047
sizeOfStream += 4 ;
971
1048
if ( orderId != null )
@@ -1007,6 +1084,12 @@ internal void Send(int[] clientIds, string messageType, string channelName, byte
1007
1084
1008
1085
internal void Send ( List < int > clientIds , string messageType , string channelName , byte [ ] data , uint ? networkId = null , ushort ? orderId = null )
1009
1086
{
1087
+ if ( NetworkConfig . EncryptedChannels . Contains ( MessageManager . channels [ channelName ] ) )
1088
+ {
1089
+ Debug . LogWarning ( "MLAPI: Cannot send messages over encrypted channel to multiple clients." ) ;
1090
+ return ;
1091
+ }
1092
+
1010
1093
//2 bytes for messageType, 2 bytes for buffer length and one byte for target bool
1011
1094
int sizeOfStream = 6 ;
1012
1095
if ( networkId != null )
@@ -1050,6 +1133,12 @@ internal void Send(List<int> clientIds, string messageType, string channelName,
1050
1133
1051
1134
internal void Send ( string messageType , string channelName , byte [ ] data , uint ? networkId = null , ushort ? orderId = null )
1052
1135
{
1136
+ if ( NetworkConfig . EncryptedChannels . Contains ( MessageManager . channels [ channelName ] ) )
1137
+ {
1138
+ Debug . LogWarning ( "MLAPI: Cannot send messages over encrypted channel to multiple clients." ) ;
1139
+ return ;
1140
+ }
1141
+
1053
1142
//2 bytes for messageType, 2 bytes for buffer length and one byte for target bool
1054
1143
int sizeOfStream = 6 ;
1055
1144
if ( networkId != null )
@@ -1094,6 +1183,12 @@ internal void Send(string messageType, string channelName, byte[] data, uint? ne
1094
1183
1095
1184
internal void Send ( string messageType , string channelName , byte [ ] data , int clientIdToIgnore , uint ? networkId = null , ushort ? orderId = null )
1096
1185
{
1186
+ if ( NetworkConfig . EncryptedChannels . Contains ( MessageManager . channels [ channelName ] ) )
1187
+ {
1188
+ Debug . LogWarning ( "MLAPI: Cannot send messages over encrypted channel to multiple clients." ) ;
1189
+ return ;
1190
+ }
1191
+
1097
1192
//2 bytes for messageType, 2 bytes for buffer length and one byte for target bool
1098
1193
int sizeOfStream = 5 ;
1099
1194
if ( networkId != null )
@@ -1142,10 +1237,16 @@ private void DisconnectClient(int clientId)
1142
1237
{
1143
1238
if ( ! isServer )
1144
1239
return ;
1240
+
1145
1241
if ( pendingClients . Contains ( clientId ) )
1146
1242
pendingClients . Remove ( clientId ) ;
1243
+
1147
1244
if ( connectedClients . ContainsKey ( clientId ) )
1148
1245
connectedClients . Remove ( clientId ) ;
1246
+
1247
+ if ( diffieHellmanPublicKeys . ContainsKey ( clientId ) )
1248
+ diffieHellmanPublicKeys . Remove ( clientId ) ;
1249
+
1149
1250
NetworkTransport . Disconnect ( hostId , clientId , out error ) ;
1150
1251
}
1151
1252
@@ -1188,9 +1289,23 @@ private void HandleApproval(int clientId, bool approved)
1188
1289
//Inform new client it got approved
1189
1290
if ( pendingClients . Contains ( clientId ) )
1190
1291
pendingClients . Remove ( clientId ) ;
1292
+
1293
+ byte [ ] aesKey = new byte [ 0 ] ;
1294
+ byte [ ] publicKey = new byte [ 0 ] ;
1295
+ if ( NetworkConfig . EnableEncryption )
1296
+ {
1297
+ EllipticDiffieHellman diffieHellman = new EllipticDiffieHellman ( EllipticDiffieHellman . DEFAULT_CURVE , EllipticDiffieHellman . DEFAULT_GENERATOR , EllipticDiffieHellman . DEFAULT_ORDER ) ;
1298
+ aesKey = diffieHellman . GetSharedSecret ( diffieHellmanPublicKeys [ clientId ] ) ;
1299
+ publicKey = diffieHellman . GetPublicKey ( ) ;
1300
+
1301
+ if ( diffieHellmanPublicKeys . ContainsKey ( clientId ) )
1302
+ diffieHellmanPublicKeys . Remove ( clientId ) ;
1303
+ }
1304
+
1191
1305
NetworkedClient client = new NetworkedClient ( )
1192
1306
{
1193
- ClientId = clientId
1307
+ ClientId = clientId ,
1308
+ AesKey = aesKey
1194
1309
} ;
1195
1310
connectedClients . Add ( clientId , client ) ;
1196
1311
@@ -1201,7 +1316,6 @@ private void HandleApproval(int clientId, bool approved)
1201
1316
connectedClients [ clientId ] . PlayerObject = go ;
1202
1317
}
1203
1318
1204
-
1205
1319
int sizeOfStream = 16 + ( ( connectedClients . Count - 1 ) * 4 ) ;
1206
1320
1207
1321
int amountOfObjectsToSend = SpawnManager . spawnedObjects . Values . Count ( x => x . ServerOnly == false ) ;
@@ -1211,6 +1325,10 @@ private void HandleApproval(int clientId, bool approved)
1211
1325
sizeOfStream += 4 ;
1212
1326
sizeOfStream += 14 * amountOfObjectsToSend ;
1213
1327
}
1328
+ if ( NetworkConfig . EnableEncryption )
1329
+ {
1330
+ sizeOfStream += 2 + publicKey . Length ;
1331
+ }
1214
1332
if ( NetworkConfig . EnableSceneSwitching )
1215
1333
{
1216
1334
sizeOfStream += 4 ;
@@ -1225,8 +1343,16 @@ private void HandleApproval(int clientId, bool approved)
1225
1343
{
1226
1344
writer . Write ( NetworkSceneManager . CurrentSceneIndex ) ;
1227
1345
}
1346
+
1347
+ if ( NetworkConfig . EnableEncryption )
1348
+ {
1349
+ writer . Write ( ( ushort ) publicKey . Length ) ;
1350
+ writer . Write ( publicKey ) ;
1351
+ }
1352
+
1228
1353
writer . Write ( NetworkTime ) ;
1229
1354
writer . Write ( NetworkTransport . GetNetworkTimestamp ( ) ) ;
1355
+
1230
1356
writer . Write ( connectedClients . Count - 1 ) ;
1231
1357
foreach ( KeyValuePair < int , NetworkedClient > item in connectedClients )
1232
1358
{
@@ -1292,6 +1418,10 @@ private void HandleApproval(int clientId, bool approved)
1292
1418
{
1293
1419
if ( pendingClients . Contains ( clientId ) )
1294
1420
pendingClients . Remove ( clientId ) ;
1421
+
1422
+ if ( diffieHellmanPublicKeys . ContainsKey ( clientId ) )
1423
+ diffieHellmanPublicKeys . Remove ( clientId ) ;
1424
+
1295
1425
NetworkTransport . Disconnect ( hostId , clientId , out error ) ;
1296
1426
}
1297
1427
}
0 commit comments