1
0
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:
lidgren
2010-05-23 10:48:58 +00:00
parent 046ca06ec6
commit e63c52bd7d
7 changed files with 72 additions and 73 deletions

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);