You've already forked lidgren-network-gen3
mirror of
https://github.com/lidgren/lidgren-network-gen3.git
synced 2026-05-17 15:46:33 +09:00
SRP authentication base code added
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
@@ -20,6 +20,11 @@
|
|||||||
</SccAuxPath>
|
</SccAuxPath>
|
||||||
<SccProvider>
|
<SccProvider>
|
||||||
</SccProvider>
|
</SccProvider>
|
||||||
|
<FileUpgradeFlags>
|
||||||
|
</FileUpgradeFlags>
|
||||||
|
<UpgradeBackupLocation>
|
||||||
|
</UpgradeBackupLocation>
|
||||||
|
<OldToolsVersion>3.5</OldToolsVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
@@ -50,6 +55,9 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="NamespaceDoc.cs" />
|
<Compile Include="NamespaceDoc.cs" />
|
||||||
|
<Compile Include="NetBigInteger.cs">
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
<Compile Include="NetBitVector.cs" />
|
<Compile Include="NetBitVector.cs" />
|
||||||
<Compile Include="NetBitWriter.cs" />
|
<Compile Include="NetBitWriter.cs" />
|
||||||
<Compile Include="NetClient.cs" />
|
<Compile Include="NetClient.cs" />
|
||||||
@@ -96,6 +104,7 @@
|
|||||||
<Compile Include="NetSenderChannelBase.cs" />
|
<Compile Include="NetSenderChannelBase.cs" />
|
||||||
<Compile Include="NetSendResult.cs" />
|
<Compile Include="NetSendResult.cs" />
|
||||||
<Compile Include="NetServer.cs" />
|
<Compile Include="NetServer.cs" />
|
||||||
|
<Compile Include="NetSRP.cs" />
|
||||||
<Compile Include="NetStoredReliableMessage.cs" />
|
<Compile Include="NetStoredReliableMessage.cs" />
|
||||||
<Compile Include="NetTime.cs" />
|
<Compile Include="NetTime.cs" />
|
||||||
<Compile Include="NetTuple.cs" />
|
<Compile Include="NetTuple.cs" />
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -57,7 +57,6 @@ namespace Lidgren.Network
|
|||||||
internal int m_maximumTransmissionUnit;
|
internal int m_maximumTransmissionUnit;
|
||||||
internal bool m_autoExpandMTU;
|
internal bool m_autoExpandMTU;
|
||||||
internal float m_expandMTUFrequency;
|
internal float m_expandMTUFrequency;
|
||||||
internal float m_expandMTUFactor;
|
|
||||||
internal int m_expandMTUFailAttempts;
|
internal int m_expandMTUFailAttempts;
|
||||||
|
|
||||||
public NetPeerConfiguration(string appIdentifier)
|
public NetPeerConfiguration(string appIdentifier)
|
||||||
|
|||||||
178
Lidgren.Network/NetSRP.cs
Normal file
178
Lidgren.Network/NetSRP.cs
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
#define USE_SHA256
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Lidgren.Network
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Helper methods for implementing SRP authentication
|
||||||
|
/// </summary>
|
||||||
|
public static class NetSRP
|
||||||
|
{
|
||||||
|
private static readonly NetBigInteger N = new NetBigInteger("0115b8b692e0e045692cf280b436735c77a5a9e8a9e7ed56c965f87db5b2a2ece3", 16);
|
||||||
|
private static readonly NetBigInteger g = new NetBigInteger("2");
|
||||||
|
private static readonly NetBigInteger k = ComputeMultiplier();
|
||||||
|
|
||||||
|
private static HashAlgorithm GetHashAlgorithm()
|
||||||
|
{
|
||||||
|
#if USE_SHA256
|
||||||
|
// this does not seem to work as of yet
|
||||||
|
return SHA256.Create();
|
||||||
|
#else
|
||||||
|
return SHA1.Create();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compute multiplier (k)
|
||||||
|
/// </summary>
|
||||||
|
private static NetBigInteger ComputeMultiplier()
|
||||||
|
{
|
||||||
|
string one = NetUtility.ToHexString(N.ToByteArrayUnsigned());
|
||||||
|
string two = NetUtility.ToHexString(g.ToByteArrayUnsigned());
|
||||||
|
|
||||||
|
string ccstr = one + two.PadLeft(one.Length, '0');
|
||||||
|
byte[] cc = NetUtility.ToByteArray(ccstr);
|
||||||
|
|
||||||
|
var sha = GetHashAlgorithm();
|
||||||
|
var ccHashed = sha.ComputeHash(cc);
|
||||||
|
|
||||||
|
return new NetBigInteger(NetUtility.ToHexString(ccHashed), 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get random bits
|
||||||
|
/// </summary>
|
||||||
|
public static byte[] CreateRandomKey(int bits)
|
||||||
|
{
|
||||||
|
byte[] retval = new byte[bits / 8];
|
||||||
|
NetRandom.Instance.NextBytes(retval);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Computer private key
|
||||||
|
/// </summary>
|
||||||
|
public static byte[] ComputePrivateKey(string username, string password, byte[] salt)
|
||||||
|
{
|
||||||
|
var sha = GetHashAlgorithm();
|
||||||
|
|
||||||
|
byte[] tmp = Encoding.ASCII.GetBytes(username + ":" + password);
|
||||||
|
byte[] innerHash = sha.ComputeHash(tmp);
|
||||||
|
|
||||||
|
byte[] total = new byte[innerHash.Length + salt.Length];
|
||||||
|
Buffer.BlockCopy(salt, 0, total, 0, salt.Length);
|
||||||
|
Buffer.BlockCopy(innerHash, 0, total, salt.Length, innerHash.Length);
|
||||||
|
|
||||||
|
// x ie. H(salt || H(username || ":" || password))
|
||||||
|
return new NetBigInteger(NetUtility.ToHexString(sha.ComputeHash(total)), 16).ToByteArrayUnsigned();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a verifier that the server can later use to authenticate users later on (v)
|
||||||
|
/// </summary>
|
||||||
|
public static byte[] ComputeServerVerifier(byte[] privateKey)
|
||||||
|
{
|
||||||
|
var sha = GetHashAlgorithm();
|
||||||
|
|
||||||
|
NetBigInteger x = new NetBigInteger(NetUtility.ToHexString(privateKey), 16);
|
||||||
|
|
||||||
|
// Verifier (v) = g^x (mod N)
|
||||||
|
var serverVerifier = g.ModPow(x, N);
|
||||||
|
|
||||||
|
return serverVerifier.ToByteArrayUnsigned();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compute client public ephemeral value (A)
|
||||||
|
/// </summary>
|
||||||
|
public static byte[] ComputeClientEphemeral(byte[] clientPrivateEphemeral) // a
|
||||||
|
{
|
||||||
|
// A= g^a (mod N)
|
||||||
|
NetBigInteger a = new NetBigInteger(NetUtility.ToHexString(clientPrivateEphemeral), 16);
|
||||||
|
NetBigInteger retval = g.ModPow(a, N);
|
||||||
|
|
||||||
|
return retval.ToByteArrayUnsigned();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compute server ephemeral value (B)
|
||||||
|
/// </summary>
|
||||||
|
public static byte[] ComputeServerEphemeral(byte[] serverPrivateEphemeral, byte[] verifier) // b
|
||||||
|
{
|
||||||
|
var b = new NetBigInteger(NetUtility.ToHexString(serverPrivateEphemeral), 16);
|
||||||
|
var v = new NetBigInteger(NetUtility.ToHexString(verifier), 16);
|
||||||
|
|
||||||
|
// B = kv + g^b (mod N)
|
||||||
|
var bb = g.ModPow(b, N);
|
||||||
|
var kv = v.Multiply(k);
|
||||||
|
var B = (kv.Add(bb)).Mod(N);
|
||||||
|
|
||||||
|
return B.ToByteArrayUnsigned();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] ComputeU(byte[] clientPublicEphemeral, byte[] serverPublicEphemeral)
|
||||||
|
{
|
||||||
|
// u = SHA-1(A || B)
|
||||||
|
string one = NetUtility.ToHexString(clientPublicEphemeral);
|
||||||
|
string two = NetUtility.ToHexString(serverPublicEphemeral);
|
||||||
|
|
||||||
|
int len = 66; // Math.Max(one.Length, two.Length);
|
||||||
|
string ccstr = one.PadLeft(len, '0') + two.PadLeft(len, '0');
|
||||||
|
|
||||||
|
byte[] cc = NetUtility.ToByteArray(ccstr);
|
||||||
|
|
||||||
|
var sha = GetHashAlgorithm();
|
||||||
|
var ccHashed = sha.ComputeHash(cc);
|
||||||
|
|
||||||
|
return new NetBigInteger(NetUtility.ToHexString(ccHashed), 16).ToByteArrayUnsigned();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] ComputeServerSessionValue(byte[] clientPublicEphemeral, byte[] verifier, byte[] udata, byte[] serverPrivateEphemeral)
|
||||||
|
{
|
||||||
|
// S = (Av^u) ^ b (mod N)
|
||||||
|
var A = new NetBigInteger(NetUtility.ToHexString(clientPublicEphemeral), 16);
|
||||||
|
var v = new NetBigInteger(NetUtility.ToHexString(verifier), 16);
|
||||||
|
var u = new NetBigInteger(NetUtility.ToHexString(udata), 16);
|
||||||
|
var b = new NetBigInteger(NetUtility.ToHexString(serverPrivateEphemeral), 16);
|
||||||
|
|
||||||
|
NetBigInteger retval = v.ModPow(u, N).Multiply(A).Mod(N).ModPow(b, N).Mod(N);
|
||||||
|
|
||||||
|
return retval.ToByteArrayUnsigned();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] ComputeClientSessionValue(byte[] serverPublicEphemeral, byte[] xdata, byte[] udata, byte[] clientPrivateEphemeral)
|
||||||
|
{
|
||||||
|
// (B - kg^x) ^ (a + ux) (mod N)
|
||||||
|
var B = new NetBigInteger(NetUtility.ToHexString(serverPublicEphemeral), 16);
|
||||||
|
var x = new NetBigInteger(NetUtility.ToHexString(xdata), 16);
|
||||||
|
var u = new NetBigInteger(NetUtility.ToHexString(udata), 16);
|
||||||
|
var a = new NetBigInteger(NetUtility.ToHexString(clientPrivateEphemeral), 16);
|
||||||
|
|
||||||
|
var bx = g.ModPow(x, N);
|
||||||
|
var btmp = B.Add(N.Multiply(k)).Subtract(bx.Multiply(k)).Mod(N);
|
||||||
|
return btmp.ModPow(x.Multiply(u).Add(a), N).ToByteArrayUnsigned();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create XTEA symmetrical encryption object from sessionValue
|
||||||
|
/// </summary>
|
||||||
|
public static NetXtea CreateEncryption(byte[] sessionValue)
|
||||||
|
{
|
||||||
|
var sha = GetHashAlgorithm();
|
||||||
|
var hash = sha.ComputeHash(sessionValue);
|
||||||
|
|
||||||
|
var key = new byte[16];
|
||||||
|
for(int i=0;i<16;i++)
|
||||||
|
{
|
||||||
|
key[i] = hash[i];
|
||||||
|
for (int j = 1; j < hash.Length / 16; j++)
|
||||||
|
key[i] ^= hash[i + (j * 16)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return new NetXtea(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -56,6 +56,40 @@ namespace UnitTests
|
|||||||
if (im.ReadString() != "kokos")
|
if (im.ReadString() != "kokos")
|
||||||
throw new NetException("fail");
|
throw new NetException("fail");
|
||||||
|
|
||||||
|
byte[] salt = NetSRP.CreateRandomKey(16);
|
||||||
|
byte[] x = NetSRP.ComputePrivateKey("user", "password", salt);
|
||||||
|
|
||||||
|
byte[] v = NetSRP.ComputeServerVerifier(x);
|
||||||
|
//Console.WriteLine("v = " + NetUtility.ToHexString(v));
|
||||||
|
|
||||||
|
byte[] a = NetSRP.CreateRandomKey(32); // NetUtility.ToByteArray("393ed364924a71ba7258633cc4854d655ca4ec4e8ba833eceaad2511e80db2b5");
|
||||||
|
byte[] A = NetSRP.ComputeClientEphemeral(a);
|
||||||
|
//Console.WriteLine("A = " + NetUtility.ToHexString(A));
|
||||||
|
|
||||||
|
byte[] b = NetSRP.CreateRandomKey(32); // NetUtility.ToByteArray("cc4d87a90db91067d52e2778b802ca6f7d362490c4be294b21b4a57c71cf55a9");
|
||||||
|
byte[] B = NetSRP.ComputeServerEphemeral(b, v);
|
||||||
|
//Console.WriteLine("B = " + NetUtility.ToHexString(B));
|
||||||
|
|
||||||
|
byte[] u = NetSRP.ComputeU(A, B);
|
||||||
|
//Console.WriteLine("u = " + NetUtility.ToHexString(u));
|
||||||
|
|
||||||
|
byte[] Ss = NetSRP.ComputeServerSessionValue(A, v, u, b);
|
||||||
|
//Console.WriteLine("Ss = " + NetUtility.ToHexString(Ss));
|
||||||
|
|
||||||
|
byte[] Sc = NetSRP.ComputeClientSessionValue(B, x, u, a);
|
||||||
|
//Console.WriteLine("Sc = " + NetUtility.ToHexString(Sc));
|
||||||
|
|
||||||
|
if (Ss.Length != Sc.Length)
|
||||||
|
throw new NetException("SRP non matching lengths!");
|
||||||
|
|
||||||
|
for (int j = 0; j < Ss.Length; j++)
|
||||||
|
{
|
||||||
|
if (Ss[j] != Sc[j])
|
||||||
|
throw new NetException("SRP non matching session values!");
|
||||||
|
}
|
||||||
|
|
||||||
|
var test = NetSRP.CreateEncryption(Ss);
|
||||||
|
|
||||||
Console.WriteLine("Message encryption OK");
|
Console.WriteLine("Message encryption OK");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user