You've already forked lidgren-network-gen3
mirror of
https://github.com/lidgren/lidgren-network-gen3.git
synced 2026-05-15 22:56:30 +09:00
XTEA fixed; Message encryption working
This commit is contained in:
@@ -19,6 +19,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Security;
|
||||
|
||||
namespace Lidgren.Network
|
||||
{
|
||||
@@ -27,13 +28,11 @@ namespace Lidgren.Network
|
||||
private const int m_blockSize = 8;
|
||||
private const int m_keySize = 16;
|
||||
private const int m_delta = unchecked((int)0x9E3779B9);
|
||||
private const int m_dSum = unchecked((int)0xC6EF3720); // sum on decrypt
|
||||
|
||||
private readonly byte[] m_keyBytes;
|
||||
private readonly int[] m_key;
|
||||
private readonly int m_rounds;
|
||||
private readonly int m_numRounds;
|
||||
|
||||
public byte[] Key { get { return m_keyBytes; } }
|
||||
private uint[] m_sum0;
|
||||
private uint[] m_sum1;
|
||||
|
||||
/// <summary>
|
||||
/// 16 byte key
|
||||
@@ -42,20 +41,34 @@ namespace Lidgren.Network
|
||||
{
|
||||
if (key.Length < 16)
|
||||
throw new NetException("Key too short!");
|
||||
m_keyBytes = key;
|
||||
m_key = new int[4];
|
||||
m_key[0] = BitConverter.ToInt32(key, 0);
|
||||
m_key[1] = BitConverter.ToInt32(key, 4);
|
||||
m_key[2] = BitConverter.ToInt32(key, 8);
|
||||
m_key[3] = BitConverter.ToInt32(key, 12);
|
||||
m_rounds = rounds;
|
||||
|
||||
m_numRounds = rounds;
|
||||
|
||||
m_sum0 = new uint[m_numRounds];
|
||||
m_sum1 = new uint[m_numRounds];
|
||||
uint[] tmp = new uint[8];
|
||||
|
||||
int num2;
|
||||
int index = num2 = 0;
|
||||
while (index < 4)
|
||||
{
|
||||
tmp[index] = BitConverter.ToUInt32(key, num2);
|
||||
index++;
|
||||
num2 += 4;
|
||||
}
|
||||
for (index = num2 = 0; index < 32; index++)
|
||||
{
|
||||
m_sum0[index] = ((uint)num2) + tmp[num2 & 3];
|
||||
num2 += -1640531527;
|
||||
m_sum1[index] = ((uint)num2) + tmp[(num2 >> 11) & 3];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 16 byte key
|
||||
/// </summary>
|
||||
public NetXtea(byte[] key)
|
||||
: this(key, 64)
|
||||
: this(key, 32)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -65,25 +78,21 @@ namespace Lidgren.Network
|
||||
byte[] outBytes,
|
||||
int outOff)
|
||||
{
|
||||
// Pack bytes into integers
|
||||
int v0 = BytesToInt(inBytes, inOff);
|
||||
int v1 = BytesToInt(inBytes, inOff + 4);
|
||||
uint v0 = BytesToUInt(inBytes, inOff);
|
||||
uint v1 = BytesToUInt(inBytes, inOff + 4);
|
||||
|
||||
int sum = 0;
|
||||
|
||||
for (int i = 0; i != m_rounds; i++)
|
||||
for (int i = 0; i != m_numRounds; i++)
|
||||
{
|
||||
v0 += ((v1 << 4 ^ (int)((uint)v1 >> 5)) + v1) ^ (sum + m_key[sum & 3]);
|
||||
sum += m_delta;
|
||||
v1 += ((v0 << 4 ^ (int)((uint)v0 >> 5)) + v0) ^ (sum + m_key[(int)((uint)sum >> 11) & 3]);
|
||||
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ m_sum0[i];
|
||||
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ m_sum1[i];
|
||||
}
|
||||
|
||||
UnpackInt(v0, outBytes, outOff);
|
||||
UnpackInt(v1, outBytes, outOff + 4);
|
||||
UIntToBytes(v0, outBytes, outOff);
|
||||
UIntToBytes(v1, outBytes, outOff + 4);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
public void DecryptBlock(
|
||||
byte[] inBytes,
|
||||
int inOff,
|
||||
@@ -91,43 +100,35 @@ namespace Lidgren.Network
|
||||
int outOff)
|
||||
{
|
||||
// Pack bytes into integers
|
||||
int v0 = BytesToInt(inBytes, inOff);
|
||||
int v1 = BytesToInt(inBytes, inOff + 4);
|
||||
uint v0 = BytesToUInt(inBytes, inOff);
|
||||
uint v1 = BytesToUInt(inBytes, inOff + 4);
|
||||
|
||||
int sum = m_dSum;
|
||||
|
||||
for (int i = 0; i != m_rounds; i++)
|
||||
for (int i = m_numRounds - 1; i >= 0; i--)
|
||||
{
|
||||
v1 -= ((v0 << 4 ^ (int)((uint)v0 >> 5)) + v0) ^ (sum + m_key[(int)((uint)sum >> 11) & 3]);
|
||||
sum -= m_delta;
|
||||
v0 -= ((v1 << 4 ^ (int)((uint)v1 >> 5)) + v1) ^ (sum + m_key[sum & 3]);
|
||||
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ m_sum1[i];
|
||||
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ m_sum0[i];
|
||||
}
|
||||
|
||||
UnpackInt(v0, outBytes, outOff);
|
||||
UnpackInt(v1, outBytes, outOff + 4);
|
||||
UIntToBytes(v0, outBytes, outOff);
|
||||
UIntToBytes(v1, outBytes, outOff + 4);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private static int BytesToInt(byte[] b, int inOff)
|
||||
private static uint BytesToUInt(byte[] bytes, int offset)
|
||||
{
|
||||
//return BitConverter.ToInt32(b, inOff);
|
||||
return ((b[inOff++]) << 24) |
|
||||
((b[inOff++] & 255) << 16) |
|
||||
((b[inOff++] & 255) << 8) |
|
||||
((b[inOff] & 255));
|
||||
uint retval = (uint)(bytes[offset] << 24);
|
||||
retval |= (uint)(bytes[++offset] << 16);
|
||||
retval |= (uint)(bytes[++offset] << 8);
|
||||
return (retval | bytes[++offset]);
|
||||
}
|
||||
|
||||
private static void UnpackInt(
|
||||
int v,
|
||||
byte[] b,
|
||||
int outOff)
|
||||
private static void UIntToBytes(uint value, byte[] destination, int destinationOffset)
|
||||
{
|
||||
uint uv = (uint)v;
|
||||
b[outOff++] = (byte)(uv >> 24);
|
||||
b[outOff++] = (byte)(uv >> 16);
|
||||
b[outOff++] = (byte)(uv >> 8);
|
||||
b[outOff] = (byte)uv;
|
||||
destination[destinationOffset++] = (byte)(value >> 24);
|
||||
destination[destinationOffset++] = (byte)(value >> 16);
|
||||
destination[destinationOffset++] = (byte)(value >> 8);
|
||||
destination[destinationOffset++] = (byte)value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -119,15 +119,14 @@ namespace Lidgren.Network
|
||||
|
||||
public void Decrypt(NetXtea tea)
|
||||
{
|
||||
// need blocks of 8 bytes
|
||||
// requires blocks of 8 bytes
|
||||
int blocks = m_bitLength / 64;
|
||||
if (blocks * 64 != m_bitLength)
|
||||
throw new NetException("Wrong message length for XTEA decrypt! Length is " + m_bitLength + " bits");
|
||||
|
||||
Console.WriteLine("DECRYPTING " + NetUtility.ToHexString(m_data));
|
||||
|
||||
byte[] result = new byte[m_data.Length];
|
||||
tea.DecryptBlock(m_data, 0, result, 0);
|
||||
for (int i = 0; i < blocks; i++)
|
||||
tea.DecryptBlock(m_data, (i * 8), result, (i * 8));
|
||||
m_data = result;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Lidgren.Network
|
||||
MethodInfo[] methods = typeof(NetOutgoingMessage).GetMethods(BindingFlags.Instance | BindingFlags.Public);
|
||||
foreach (MethodInfo mi in methods)
|
||||
{
|
||||
if (mi.Name == "Write")
|
||||
if (mi.Name.Equals("Write", StringComparison.InvariantCulture))
|
||||
{
|
||||
ParameterInfo[] pis = mi.GetParameters();
|
||||
if (pis.Length == 1)
|
||||
|
||||
@@ -172,13 +172,13 @@ namespace Lidgren.Network
|
||||
WritePadBits();
|
||||
int blocksNeeded = (m_bitLength + 63) / 64;
|
||||
int missingBits = (blocksNeeded * 64) - m_bitLength;
|
||||
int missingBytes = missingBits / 8;
|
||||
int missingBytes = NetUtility.BytesToHoldBits(missingBits);
|
||||
for (int i = 0; i < missingBytes; i++)
|
||||
Write((byte)0);
|
||||
|
||||
Console.WriteLine("ENCRYPTING " + NetUtility.ToHexString(m_data));
|
||||
byte[] result = new byte[m_data.Length];
|
||||
tea.EncryptBlock(m_data, 0, result, 0);
|
||||
for(int i=0;i<blocksNeeded;i++)
|
||||
tea.EncryptBlock(m_data, (i * 8), result, (i * 8));
|
||||
m_data = result;
|
||||
}
|
||||
|
||||
|
||||
@@ -479,7 +479,7 @@ namespace Lidgren.Network
|
||||
break;
|
||||
}
|
||||
|
||||
if (appIdent.Equals(m_configuration.AppIdentifier) == false)
|
||||
if (appIdent.Equals(m_configuration.AppIdentifier, StringComparison.InvariantCulture) == false)
|
||||
{
|
||||
// wrong app ident
|
||||
LogWarning("Connect received with wrong appidentifier (need '" + m_configuration.AppIdentifier + "' found '" + appIdent + "') from " + senderEndpoint);
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace Lidgren.Network
|
||||
{
|
||||
if (string.IsNullOrEmpty(appIdentifier))
|
||||
throw new NetException("App identifier must be at least one character long");
|
||||
m_appIdentifier = appIdentifier;
|
||||
m_appIdentifier = appIdentifier.ToString(System.Globalization.CultureInfo.InvariantCulture);
|
||||
|
||||
// defaults
|
||||
m_isLocked = false;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Text;
|
||||
|
||||
using Lidgren.Network;
|
||||
using System.Security;
|
||||
|
||||
namespace UnitTests
|
||||
{
|
||||
@@ -14,20 +15,23 @@ namespace UnitTests
|
||||
//
|
||||
NetXtea xtea = new NetXtea(NetSha.Hash(Encoding.ASCII.GetBytes("TopSecret")));
|
||||
|
||||
byte[] test = new byte[16];
|
||||
NetRandom.Instance.NextBytes(test);
|
||||
byte[] original = new byte[16];
|
||||
NetRandom.Instance.NextBytes(original);
|
||||
|
||||
byte[] encrypted = new byte[test.Length];
|
||||
xtea.EncryptBlock(test, 0, encrypted, 0);
|
||||
byte[] encrypted = new byte[original.Length];
|
||||
xtea.EncryptBlock(original, 0, encrypted, 0);
|
||||
xtea.EncryptBlock(original, 8, encrypted, 8);
|
||||
|
||||
byte[] decrypted = new byte[test.Length];
|
||||
byte[] decrypted = new byte[original.Length];
|
||||
xtea.DecryptBlock(encrypted, 0, decrypted, 0);
|
||||
xtea.DecryptBlock(encrypted, 8, decrypted, 8);
|
||||
|
||||
// compare!
|
||||
for (int i = 0; i < test.Length; i++)
|
||||
if (test[i] != decrypted[i])
|
||||
for (int i = 0; i < original.Length; i++)
|
||||
if (original[i] != decrypted[i])
|
||||
throw new NetException("XTEA fail!");
|
||||
|
||||
Console.WriteLine("XTEA OK");
|
||||
|
||||
NetOutgoingMessage om = peer.CreateMessage();
|
||||
om.Write("Hallon");
|
||||
@@ -35,16 +39,11 @@ namespace UnitTests
|
||||
om.Write(5, 5);
|
||||
om.Write(true);
|
||||
om.Write("kokos");
|
||||
|
||||
Console.WriteLine("Pre encryption: " + NetUtility.ToHexString(om.PeekDataBuffer()));
|
||||
om.Encrypt(xtea);
|
||||
Console.WriteLine("Post encryption: " + NetUtility.ToHexString(om.PeekDataBuffer()));
|
||||
|
||||
// convert to incoming message
|
||||
NetIncomingMessage im = Program.CreateIncomingMessage(om.PeekDataBuffer(), om.LengthBits);
|
||||
Console.WriteLine("Pre decryption: " + NetUtility.ToHexString(im.PeekDataBuffer()));
|
||||
im.Decrypt(xtea);
|
||||
Console.WriteLine("Post decryption: " + NetUtility.ToHexString(im.PeekDataBuffer()));
|
||||
|
||||
if (im.ReadString() != "Hallon")
|
||||
throw new NetException("fail");
|
||||
@@ -57,7 +56,7 @@ namespace UnitTests
|
||||
if (im.ReadString() != "kokos")
|
||||
throw new NetException("fail");
|
||||
|
||||
|
||||
Console.WriteLine("Message encryption OK");
|
||||
|
||||
byte[] salt = NetUtility.ToByteArray("e6fb7e23f001f3e6c081"); // s
|
||||
byte[] verifier = NetSRP.ComputePasswordVerifier("user", "password", salt);
|
||||
|
||||
Reference in New Issue
Block a user