Guest User

SRP.cs

a guest
Mar 9th, 2016
463
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.09 KB | None | 0 0
  1. using System;
  2. using System.Linq;
  3. using System.Numerics;
  4. using System.Security.Cryptography;
  5. using System.Text;
  6.  
  7. namespace FS_Login
  8. {
  9.     public class SRP
  10.     {
  11.         private Random m_Random { get; set; }
  12.         private SHA1Managed m_SHA1Managed { get; set; }
  13.  
  14.         public string AccountName { get; set; }
  15.         public string PasswordHash { get; set; }
  16.         public BigInteger g { get; } = new BigInteger(7);
  17.         public BigInteger k { get; } = new BigInteger(3);
  18.         public BigInteger K { get; private set; }
  19.         public BigInteger N { get; } = new BigInteger(new byte[] { 137, 75, 100, 94, 137, 225, 83, 91, 189, 173, 91, 139, 41, 6, 80, 83, 8, 1, 177, 142, 191, 191, 94, 143, 171, 60, 130, 135, 42, 62, 155, 183 });
  20.         public BigInteger A { get; set; }
  21.         public BigInteger b { get; private set; }
  22.         public BigInteger B { get; private set; }
  23.         public BigInteger u { get; private set; }
  24.         public BigInteger M1 { get; set; }
  25.         public BigInteger M2 { get; private set; }
  26.         public BigInteger s { get; } =  new BigInteger(new byte[] { 173, 208, 58, 49, 210, 113, 20, 70, 117, 242, 112, 126, 80, 38, 182, 210, 241, 134, 89, 153, 118, 2, 80, 170, 185, 69, 224, 158, 221, 42, 163, 69 });
  27.         public BigInteger v { get; set; }
  28.         public BigInteger x { get; private set; }
  29.  
  30.  
  31.         public SRP()
  32.         {
  33.             m_Random = new Random();
  34.             m_SHA1Managed = new SHA1Managed();
  35.         }
  36.  
  37.         public bool OnLogonChallenge()
  38.         {
  39.             byte[] saltNamePassword = new byte[0]
  40.                 .Concat(s.ToByteArray())
  41.                 .Concat(Encoding.UTF8.GetBytes(AccountName + ":" + PasswordHash)).ToArray();
  42.  
  43.             byte[] hashedNamePasswordHash = new byte[0]
  44.                 .Concat(m_SHA1Managed.ComputeHash(saltNamePassword))
  45.                 .Concat(new byte[] { 0 }).ToArray();
  46.  
  47.             x = new BigInteger(hashedNamePasswordHash);
  48.  
  49.             v = BigInteger.ModPow(g, x, N);
  50.  
  51.             byte[] tempBytes = new byte[32];
  52.             m_Random.NextBytes(tempBytes);
  53.             // We want a positive number for calculations
  54.             tempBytes[tempBytes.Length - 1] = 0;
  55.             b = new BigInteger(tempBytes);
  56.  
  57.             B = ((k * v) + BigInteger.ModPow(g, b, N)) % N;
  58.             return true;
  59.         }
  60.  
  61.         public bool OnLogonProof()
  62.         {
  63.             if (A % N == 0)
  64.                 return false;
  65.  
  66.             byte[] ABBytes = new byte[0]
  67.                 .Concat(A.ToByteArray())
  68.                 .Concat(B.ToByteArray()).ToArray();
  69.  
  70.             byte[] hashedABBytes = new byte[0]
  71.                 .Concat(m_SHA1Managed.ComputeHash(ABBytes))
  72.                 .Concat(new byte[] { 0 }).ToArray();
  73.  
  74.             u = new BigInteger(hashedABBytes.ToArray());
  75.  
  76.             BigInteger S = BigInteger.ModPow((A * (BigInteger.ModPow(v, u, N))), b, N);
  77.  
  78.             /*** ERROR ***/
  79.             // You have to make a custom SHA-1 Interleave hash function, the regular won't do.
  80.             // See http://tools.ietf.org/rfc/rfc2945.txt
  81.             byte[] hashedSBytes = m_SHA1Managed.ComputeHash(S.ToByteArray());
  82.             K = new BigInteger(hashedSBytes.ToArray());
  83.  
  84.             byte[] hashedNBytes = m_SHA1Managed.ComputeHash(N.ToByteArray());
  85.             BigInteger hashedN = new BigInteger(hashedNBytes);
  86.            
  87.             byte[] hashedGBytes = m_SHA1Managed.ComputeHash(g.ToByteArray());
  88.             BigInteger hashedG = new BigInteger(hashedGBytes.ToArray());
  89.            
  90.             byte[] hashedAccountBytes = m_SHA1Managed.ComputeHash(Encoding.UTF8.GetBytes(AccountName));
  91.  
  92.             /* BigInteger hashedAccountName = new BigInteger(hashedAccountBytes.ToArray());
  93.                 This is just wrong - it reverses the byte ordering and it shouldn't have.
  94.                 Not here at least.
  95.             */
  96.             byte[] NxorG = new byte[20];
  97.             for(int i = 0;i<NxorG.Length;i++)
  98.             {
  99.                 NxorG[i] = (byte)(hashedN.ToByteArray()[i] ^ hashedG.ToByteArray()[i]);
  100.             }
  101.  
  102.             byte[] allBytes = new byte[0]
  103.                 .Concat(NxorG)
  104.                 //.Concat(hashedAccountName.ToByteArray()) // Wrong
  105.                 .Concat(hashedAccountBytes) //Correct
  106.                 .Concat(s.ToByteArray())
  107.                 .Concat(A.ToByteArray())
  108.                 .Concat(B.ToByteArray())
  109.                 .Concat(K.ToByteArray()).ToArray();
  110.  
  111.             // This is a server-side check against M1, sent from the client - they should match.
  112.             BigInteger MS = new BigInteger(m_SHA1Managed.ComputeHash(allBytes));
  113.  
  114.             byte[] testBytes = new byte[0]
  115.                 .Concat(A.ToByteArray())
  116.                 .Concat(M1.ToByteArray())
  117.                 .Concat(K.ToByteArray()).ToArray();
  118.  
  119.             // i think this is actually the server calculation, not MS
  120.             // Indeed, this is not MS (or M1 for that matter).
  121.             // This is server's proof of session key, required to prove
  122.             // the client that this is indeed the server with which he/she registered.
  123.             M2 = new BigInteger(m_SHA1Managed.ComputeHash(testBytes.ToArray()));
  124.  
  125.             if (M2 != M1)
  126.                 return false;
  127.  
  128.             return true;
  129.         }
  130.     }
  131. }
Add Comment
Please, Sign In to add comment