Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Linq;
- using System.Numerics;
- using System.Security.Cryptography;
- using System.Text;
- namespace FS_Login
- {
- public class SRP
- {
- private Random m_Random { get; set; }
- private SHA1Managed m_SHA1Managed { get; set; }
- public string AccountName { get; set; }
- public string PasswordHash { get; set; }
- public BigInteger g { get; } = new BigInteger(7);
- public BigInteger k { get; } = new BigInteger(3);
- public BigInteger K { get; private set; }
- 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 });
- public BigInteger A { get; set; }
- public BigInteger b { get; private set; }
- public BigInteger B { get; private set; }
- public BigInteger u { get; private set; }
- public BigInteger M1 { get; set; }
- public BigInteger M2 { get; private set; }
- 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 });
- public BigInteger v { get; set; }
- public BigInteger x { get; private set; }
- public SRP()
- {
- m_Random = new Random();
- m_SHA1Managed = new SHA1Managed();
- }
- public bool OnLogonChallenge()
- {
- byte[] saltNamePassword = new byte[0]
- .Concat(s.ToByteArray())
- .Concat(Encoding.UTF8.GetBytes(AccountName + ":" + PasswordHash)).ToArray();
- byte[] hashedNamePasswordHash = new byte[0]
- .Concat(m_SHA1Managed.ComputeHash(saltNamePassword))
- .Concat(new byte[] { 0 }).ToArray();
- x = new BigInteger(hashedNamePasswordHash);
- v = BigInteger.ModPow(g, x, N);
- byte[] tempBytes = new byte[32];
- m_Random.NextBytes(tempBytes);
- // We want a positive number for calculations
- tempBytes[tempBytes.Length - 1] = 0;
- b = new BigInteger(tempBytes);
- B = ((k * v) + BigInteger.ModPow(g, b, N)) % N;
- return true;
- }
- public bool OnLogonProof()
- {
- if (A % N == 0)
- return false;
- byte[] ABBytes = new byte[0]
- .Concat(A.ToByteArray())
- .Concat(B.ToByteArray()).ToArray();
- byte[] hashedABBytes = new byte[0]
- .Concat(m_SHA1Managed.ComputeHash(ABBytes))
- .Concat(new byte[] { 0 }).ToArray();
- u = new BigInteger(hashedABBytes.ToArray());
- BigInteger S = BigInteger.ModPow((A * (BigInteger.ModPow(v, u, N))), b, N);
- /*** ERROR ***/
- // You have to make a custom SHA-1 Interleave hash function, the regular won't do.
- // See http://tools.ietf.org/rfc/rfc2945.txt
- byte[] hashedSBytes = m_SHA1Managed.ComputeHash(S.ToByteArray());
- K = new BigInteger(hashedSBytes.ToArray());
- byte[] hashedNBytes = m_SHA1Managed.ComputeHash(N.ToByteArray());
- BigInteger hashedN = new BigInteger(hashedNBytes);
- byte[] hashedGBytes = m_SHA1Managed.ComputeHash(g.ToByteArray());
- BigInteger hashedG = new BigInteger(hashedGBytes.ToArray());
- byte[] hashedAccountBytes = m_SHA1Managed.ComputeHash(Encoding.UTF8.GetBytes(AccountName));
- /* BigInteger hashedAccountName = new BigInteger(hashedAccountBytes.ToArray());
- This is just wrong - it reverses the byte ordering and it shouldn't have.
- Not here at least.
- */
- byte[] NxorG = new byte[20];
- for(int i = 0;i<NxorG.Length;i++)
- {
- NxorG[i] = (byte)(hashedN.ToByteArray()[i] ^ hashedG.ToByteArray()[i]);
- }
- byte[] allBytes = new byte[0]
- .Concat(NxorG)
- //.Concat(hashedAccountName.ToByteArray()) // Wrong
- .Concat(hashedAccountBytes) //Correct
- .Concat(s.ToByteArray())
- .Concat(A.ToByteArray())
- .Concat(B.ToByteArray())
- .Concat(K.ToByteArray()).ToArray();
- // This is a server-side check against M1, sent from the client - they should match.
- BigInteger MS = new BigInteger(m_SHA1Managed.ComputeHash(allBytes));
- byte[] testBytes = new byte[0]
- .Concat(A.ToByteArray())
- .Concat(M1.ToByteArray())
- .Concat(K.ToByteArray()).ToArray();
- // i think this is actually the server calculation, not MS
- // Indeed, this is not MS (or M1 for that matter).
- // This is server's proof of session key, required to prove
- // the client that this is indeed the server with which he/she registered.
- M2 = new BigInteger(m_SHA1Managed.ComputeHash(testBytes.ToArray()));
- if (M2 != M1)
- return false;
- return true;
- }
- }
- }
Add Comment
Please, Sign In to add comment