@@ -49,6 +49,10 @@ public bool isHost
49
49
50
50
public NetworkingConfiguration NetworkConfig ;
51
51
52
+ private EllipticDiffieHellman clientDiffieHellman ;
53
+ private Dictionary < int , byte [ ] > diffieHellmanPublicKeys ;
54
+ private byte [ ] clientAesKey ;
55
+
52
56
private void OnValidate ( )
53
57
{
54
58
if ( SpawnablePrefabs != null )
@@ -86,6 +90,7 @@ private ConnectionConfig Init(NetworkingConfiguration netConfig)
86
90
pendingClients = new HashSet < int > ( ) ;
87
91
connectedClients = new Dictionary < int , NetworkedClient > ( ) ;
88
92
messageBuffer = new byte [ NetworkConfig . MessageBufferSize ] ;
93
+ diffieHellmanPublicKeys = new Dictionary < int , byte [ ] > ( ) ;
89
94
MessageManager . channels = new Dictionary < string , int > ( ) ;
90
95
MessageManager . messageTypes = new Dictionary < string , ushort > ( ) ;
91
96
MessageManager . messageCallbacks = new Dictionary < ushort , Dictionary < int , Action < int , byte [ ] > > > ( ) ;
@@ -372,15 +377,29 @@ private void Update()
372
377
}
373
378
else
374
379
{
380
+ byte [ ] diffiePublic = new byte [ 0 ] ;
381
+ if ( NetworkConfig . EnableEncryption )
382
+ {
383
+ clientDiffieHellman = new EllipticDiffieHellman ( EllipticDiffieHellman . DEFAULT_CURVE , EllipticDiffieHellman . DEFAULT_GENERATOR , EllipticDiffieHellman . DEFAULT_ORDER ) ;
384
+ diffiePublic = clientDiffieHellman . GetPublicKey ( ) ;
385
+ }
386
+
375
387
int sizeOfStream = 32 ;
376
388
if ( NetworkConfig . ConnectionApproval )
377
389
sizeOfStream += 2 + NetworkConfig . ConnectionData . Length ;
390
+ if ( NetworkConfig . EnableEncryption )
391
+ sizeOfStream += 2 + diffiePublic . Length ;
378
392
379
393
using ( MemoryStream writeStream = new MemoryStream ( sizeOfStream ) )
380
394
{
381
395
using ( BinaryWriter writer = new BinaryWriter ( writeStream ) )
382
396
{
383
397
writer . Write ( NetworkConfig . GetConfig ( ) ) ;
398
+ if ( NetworkConfig . EnableEncryption )
399
+ {
400
+ writer . Write ( ( ushort ) diffiePublic . Length ) ;
401
+ writer . Write ( diffiePublic ) ;
402
+ }
384
403
if ( NetworkConfig . ConnectionApproval )
385
404
{
386
405
writer . Write ( ( ushort ) NetworkConfig . ConnectionData . Length ) ;
@@ -469,6 +488,14 @@ private void HandleIncomingData(int clientId, byte[] data, int channelId)
469
488
470
489
ushort bytesToRead = reader . ReadUInt16 ( ) ;
471
490
byte [ ] incommingData = reader . ReadBytes ( bytesToRead ) ;
491
+ if ( NetworkConfig . EncryptedChannels . Contains ( channelId ) )
492
+ {
493
+ //Encrypted message
494
+ if ( isServer )
495
+ incommingData = CryptographyHelper . Decrypt ( incommingData , connectedClients [ clientId ] . AesKey ) ;
496
+ else
497
+ incommingData = CryptographyHelper . Decrypt ( incommingData , clientAesKey ) ;
498
+ }
472
499
473
500
if ( isServer && isPassthrough && ! NetworkConfig . RegisteredPassthroughMessageTypes . Contains ( messageType ) )
474
501
{
@@ -550,6 +577,18 @@ private void HandleIncomingData(int clientId, byte[] data, int channelId)
550
577
DisconnectClient ( clientId ) ;
551
578
return ;
552
579
}
580
+ byte [ ] aesKey = new byte [ 0 ] ;
581
+ if ( NetworkConfig . EnableEncryption )
582
+ {
583
+ ushort diffiePublicSize = reader . ReadUInt16 ( ) ;
584
+ byte [ ] diffiePublic = reader . ReadBytes ( diffiePublicSize ) ;
585
+ diffieHellmanPublicKeys . Add ( clientId , diffiePublic ) ;
586
+ /*
587
+ EllipticDiffieHellman diffieHellman = new EllipticDiffieHellman(EllipticDiffieHellman.DEFAULT_CURVE, EllipticDiffieHellman.DEFAULT_GENERATOR, EllipticDiffieHellman.DEFAULT_ORDER);
588
+ aesKey = diffieHellman.GetSharedSecret(diffiePublic);
589
+ */
590
+
591
+ }
553
592
if ( NetworkConfig . ConnectionApproval )
554
593
{
555
594
ushort bufferSize = messageReader . ReadUInt16 ( ) ;
@@ -578,6 +617,12 @@ private void HandleIncomingData(int clientId, byte[] data, int channelId)
578
617
sceneIndex = messageReader . ReadUInt32 ( ) ;
579
618
}
580
619
620
+ if ( NetworkConfig . EnableEncryption )
621
+ {
622
+ ushort keyLength = reader . ReadUInt16 ( ) ;
623
+ clientAesKey = clientDiffieHellman . GetSharedSecret ( reader . ReadBytes ( keyLength ) ) ;
624
+ }
625
+
581
626
float netTime = messageReader . ReadSingle ( ) ;
582
627
int remoteStamp = messageReader . ReadInt32 ( ) ;
583
628
int msDelay = NetworkTransport . GetRemoteDelayTimeMS ( hostId , clientId , remoteStamp , out error ) ;
@@ -894,8 +939,18 @@ internal void PassthroughSend(int targetId, int sourceId, ushort messageType, in
894
939
writer . Write ( orderId . Value ) ;
895
940
writer . Write ( true ) ;
896
941
writer . Write ( sourceId ) ;
897
- writer . Write ( ( ushort ) data . Length ) ;
898
- writer . Write ( data ) ;
942
+ if ( NetworkConfig . EncryptedChannels . Contains ( channelId ) )
943
+ {
944
+ //Encrypted message
945
+ byte [ ] encrypted = CryptographyHelper . Encrypt ( data , connectedClients [ targetId ] . AesKey ) ;
946
+ writer . Write ( ( ushort ) encrypted . Length ) ;
947
+ writer . Write ( encrypted ) ;
948
+ }
949
+ else
950
+ {
951
+ writer . Write ( ( ushort ) data . Length ) ;
952
+ writer . Write ( data ) ;
953
+ }
899
954
}
900
955
NetworkTransport . QueueMessageForSending ( hostId , targetId , channelId , stream . GetBuffer ( ) , sizeOfStream , out error ) ;
901
956
}
@@ -944,8 +999,25 @@ internal void Send(int clientId, string messageType, string channelName, byte[]
944
999
writer . Write ( isPassthrough ) ;
945
1000
if ( isPassthrough )
946
1001
writer . Write ( clientId ) ;
947
- writer . Write ( ( ushort ) data . Length ) ;
948
- writer . Write ( data ) ;
1002
+
1003
+ if ( NetworkConfig . EncryptedChannels . Contains ( MessageManager . channels [ channelName ] ) )
1004
+ {
1005
+ //This is an encrypted message.
1006
+ byte [ ] encrypted ;
1007
+ if ( isServer )
1008
+ encrypted = CryptographyHelper . Encrypt ( data , connectedClients [ clientId ] . AesKey ) ;
1009
+ else
1010
+ encrypted = CryptographyHelper . Encrypt ( data , clientAesKey ) ;
1011
+
1012
+ writer . Write ( ( ushort ) encrypted . Length ) ;
1013
+ writer . Write ( encrypted ) ;
1014
+ }
1015
+ else
1016
+ {
1017
+ //Send in plaintext.
1018
+ writer . Write ( ( ushort ) data . Length ) ;
1019
+ writer . Write ( data ) ;
1020
+ }
949
1021
}
950
1022
if ( isPassthrough )
951
1023
clientId = serverClientId ;
@@ -958,7 +1030,12 @@ internal void Send(int clientId, string messageType, string channelName, byte[]
958
1030
959
1031
internal void Send ( int [ ] clientIds , string messageType , string channelName , byte [ ] data , uint ? networkId = null , ushort ? orderId = null )
960
1032
{
961
- int sizeOfStream = 6 ;
1033
+ if ( NetworkConfig . EncryptedChannels . Contains ( MessageManager . channels [ channelName ] ) )
1034
+ {
1035
+ Debug . LogWarning ( "MLAPI: Cannot send messages over encrypted channel to multiple clients." ) ;
1036
+ return ;
1037
+ }
1038
+ int sizeOfStream = 6 ;
962
1039
if ( networkId != null )
963
1040
sizeOfStream += 4 ;
964
1041
if ( orderId != null )
@@ -1000,6 +1077,12 @@ internal void Send(int[] clientIds, string messageType, string channelName, byte
1000
1077
1001
1078
internal void Send ( List < int > clientIds , string messageType , string channelName , byte [ ] data , uint ? networkId = null , ushort ? orderId = null )
1002
1079
{
1080
+ if ( NetworkConfig . EncryptedChannels . Contains ( MessageManager . channels [ channelName ] ) )
1081
+ {
1082
+ Debug . LogWarning ( "MLAPI: Cannot send messages over encrypted channel to multiple clients." ) ;
1083
+ return ;
1084
+ }
1085
+
1003
1086
//2 bytes for messageType, 2 bytes for buffer length and one byte for target bool
1004
1087
int sizeOfStream = 6 ;
1005
1088
if ( networkId != null )
@@ -1043,6 +1126,12 @@ internal void Send(List<int> clientIds, string messageType, string channelName,
1043
1126
1044
1127
internal void Send ( string messageType , string channelName , byte [ ] data , uint ? networkId = null , ushort ? orderId = null )
1045
1128
{
1129
+ if ( NetworkConfig . EncryptedChannels . Contains ( MessageManager . channels [ channelName ] ) )
1130
+ {
1131
+ Debug . LogWarning ( "MLAPI: Cannot send messages over encrypted channel to multiple clients." ) ;
1132
+ return ;
1133
+ }
1134
+
1046
1135
//2 bytes for messageType, 2 bytes for buffer length and one byte for target bool
1047
1136
int sizeOfStream = 6 ;
1048
1137
if ( networkId != null )
@@ -1087,6 +1176,12 @@ internal void Send(string messageType, string channelName, byte[] data, uint? ne
1087
1176
1088
1177
internal void Send ( string messageType , string channelName , byte [ ] data , int clientIdToIgnore , uint ? networkId = null , ushort ? orderId = null )
1089
1178
{
1179
+ if ( NetworkConfig . EncryptedChannels . Contains ( MessageManager . channels [ channelName ] ) )
1180
+ {
1181
+ Debug . LogWarning ( "MLAPI: Cannot send messages over encrypted channel to multiple clients." ) ;
1182
+ return ;
1183
+ }
1184
+
1090
1185
//2 bytes for messageType, 2 bytes for buffer length and one byte for target bool
1091
1186
int sizeOfStream = 5 ;
1092
1187
if ( networkId != null )
@@ -1134,10 +1229,16 @@ private void DisconnectClient(int clientId)
1134
1229
{
1135
1230
if ( ! isServer )
1136
1231
return ;
1232
+
1137
1233
if ( pendingClients . Contains ( clientId ) )
1138
1234
pendingClients . Remove ( clientId ) ;
1235
+
1139
1236
if ( connectedClients . ContainsKey ( clientId ) )
1140
1237
connectedClients . Remove ( clientId ) ;
1238
+
1239
+ if ( diffieHellmanPublicKeys . ContainsKey ( clientId ) )
1240
+ diffieHellmanPublicKeys . Remove ( clientId ) ;
1241
+
1141
1242
NetworkTransport . Disconnect ( hostId , clientId , out error ) ;
1142
1243
}
1143
1244
@@ -1180,9 +1281,23 @@ private void HandleApproval(int clientId, bool approved)
1180
1281
//Inform new client it got approved
1181
1282
if ( pendingClients . Contains ( clientId ) )
1182
1283
pendingClients . Remove ( clientId ) ;
1284
+
1285
+ byte [ ] aesKey = new byte [ 0 ] ;
1286
+ byte [ ] publicKey = new byte [ 0 ] ;
1287
+ if ( NetworkConfig . EnableEncryption )
1288
+ {
1289
+ EllipticDiffieHellman diffieHellman = new EllipticDiffieHellman ( EllipticDiffieHellman . DEFAULT_CURVE , EllipticDiffieHellman . DEFAULT_GENERATOR , EllipticDiffieHellman . DEFAULT_ORDER ) ;
1290
+ aesKey = diffieHellman . GetSharedSecret ( diffieHellmanPublicKeys [ clientId ] ) ;
1291
+ publicKey = diffieHellman . GetPublicKey ( ) ;
1292
+
1293
+ if ( diffieHellmanPublicKeys . ContainsKey ( clientId ) )
1294
+ diffieHellmanPublicKeys . Remove ( clientId ) ;
1295
+ }
1296
+
1183
1297
NetworkedClient client = new NetworkedClient ( )
1184
1298
{
1185
- ClientId = clientId
1299
+ ClientId = clientId ,
1300
+ AesKey = aesKey
1186
1301
} ;
1187
1302
connectedClients . Add ( clientId , client ) ;
1188
1303
@@ -1193,7 +1308,6 @@ private void HandleApproval(int clientId, bool approved)
1193
1308
connectedClients [ clientId ] . PlayerObject = go ;
1194
1309
}
1195
1310
1196
-
1197
1311
int sizeOfStream = 16 + ( ( connectedClients . Count - 1 ) * 4 ) ;
1198
1312
1199
1313
int amountOfObjectsToSend = SpawnManager . spawnedObjects . Values . Count ( x => x . ServerOnly == false ) ;
@@ -1203,6 +1317,10 @@ private void HandleApproval(int clientId, bool approved)
1203
1317
sizeOfStream += 4 ;
1204
1318
sizeOfStream += 14 * amountOfObjectsToSend ;
1205
1319
}
1320
+ if ( NetworkConfig . EnableEncryption )
1321
+ {
1322
+ sizeOfStream += 2 + publicKey . Length ;
1323
+ }
1206
1324
if ( NetworkConfig . EnableSceneSwitching )
1207
1325
{
1208
1326
sizeOfStream += 4 ;
@@ -1217,8 +1335,16 @@ private void HandleApproval(int clientId, bool approved)
1217
1335
{
1218
1336
writer . Write ( NetworkSceneManager . CurrentSceneIndex ) ;
1219
1337
}
1338
+
1339
+ if ( NetworkConfig . EnableEncryption )
1340
+ {
1341
+ writer . Write ( ( ushort ) publicKey . Length ) ;
1342
+ writer . Write ( publicKey ) ;
1343
+ }
1344
+
1220
1345
writer . Write ( NetworkTime ) ;
1221
1346
writer . Write ( NetworkTransport . GetNetworkTimestamp ( ) ) ;
1347
+
1222
1348
writer . Write ( connectedClients . Count - 1 ) ;
1223
1349
foreach ( KeyValuePair < int , NetworkedClient > item in connectedClients )
1224
1350
{
@@ -1284,6 +1410,10 @@ private void HandleApproval(int clientId, bool approved)
1284
1410
{
1285
1411
if ( pendingClients . Contains ( clientId ) )
1286
1412
pendingClients . Remove ( clientId ) ;
1413
+
1414
+ if ( diffieHellmanPublicKeys . ContainsKey ( clientId ) )
1415
+ diffieHellmanPublicKeys . Remove ( clientId ) ;
1416
+
1287
1417
NetworkTransport . Disconnect ( hostId , clientId , out error ) ;
1288
1418
}
1289
1419
}
0 commit comments