public void ReceiveLoginStartInfo(String username, String password, BinaryWriter keyDataWriter) { if (state != 0) { throw new SRP6InvalidStateException(); } I = Encoding.ASCII.GetBytes(username); sha256.Initialize(); // this is temporary, eventually that would be saved/used differently. p = SRPHelpers.GetBigIntegerFromBytes(sha256.ComputeHash(Encoding.ASCII.GetBytes(username + ":" + password))); BigInteger x = Hash(s, p); v = BigInteger.ModPow(g, x, N); b = MakeRandomBigInteger(128); B = (((Hash(N, g) * v) % N) + (BigInteger.ModPow(g, b, N))) % N; // validated up to here. // TODO: Make the right checks for this. Byte[] s_bytes = SRPHelpers.GetBytesFromBigInteger(s); Byte[] B_bytes = SRPHelpers.GetBytesFromBigInteger(B); keyDataWriter.Write(s_bytes.Length); // 8 keyDataWriter.Write(s_bytes, 0, s_bytes.Length); keyDataWriter.Write(B_bytes.Length); // 128 keyDataWriter.Write(B_bytes, 0, B_bytes.Length); state = 1; }
private BigInteger Hash(params BigInteger[] integers) { if (integers == null || integers.Length <= 0) { throw new ArgumentException(); } sha256.Initialize(); Byte[] bytes; // iterates all but the last int lastIndex = integers.Length - 1; for (int i = 0; i < integers.Length; i++) { // padding. bytes = SRPHelpers.GetBytesFromBigInteger(integers[i]); int padding = bytes.Length % 4; sha256.TransformBlock(bytes, 0, bytes.Length, null, 0); if (padding != 0) { sha256.TransformBlock(s_bytesPadding[4 - padding], 0, 4 - padding, null, 0); } } // finalize with empty block (no modification) sha256.TransformFinalBlock(s_bytesPadding[0], 0, 0); // we need to reverse the hash result as integers. I'm unsure why, I guess the game does it. Byte[] hash = sha256.Hash; SRPHelpers.ReverseBytesAsUInt32(hash); return(SRPHelpers.GetBigIntegerFromBytes(hash)); }
public void ReceiveClientProof(BinaryReader clientKeyDataReader, BinaryWriter serverKeyDataWriter, out byte[] key) { if (state != 1) { throw new SRP6InvalidStateException(); } // receive M_c (proof) & A (public ephemerial key) Int32 len = clientKeyDataReader.ReadInt32(); BigInteger A = SRPHelpers.GetBigIntegerFromBytes(clientKeyDataReader.ReadBytes(len)); len = clientKeyDataReader.ReadInt32(); Byte[] M_clientBytes = clientKeyDataReader.ReadBytes(len); if (A == 0) // A % N ?? { throw new SRP6SafeguardException("SRP6 received invalid 'A' from server (A == 0)"); } // Reverse bytes received from server. //SRPHelpers.ReverseBytesAsUInt32(M_clientBytes); BigInteger M_client = SRPHelpers.GetBigIntegerFromBytes(M_clientBytes); // calculate random scrambling parameter BigInteger u = Hash(A, B); // compute session key (not sure about this one, check if it's the right alg) S = BigInteger.ModPow((A * BigInteger.ModPow(v, u, N)) % N, b, N); K = HashKey(S); // I think the client uses this key to encrypt. It doesnt seem to use S at all // return the key key = SRPHelpers.GetBytesFromBigInteger(K); sha256.Initialize(); Byte[] IHash = sha256.ComputeHash(I); BigInteger hash = Hash(Hash(N) ^ Hash(g), SRPHelpers.GetBigIntegerFromBytes(IHash), s, A, B, K); // Reverse the array. Byte[] bytes = SRPHelpers.GetBytesFromBigInteger(hash); SRPHelpers.ReverseBytesAsUInt32(bytes); hash = SRPHelpers.GetBigIntegerFromBytes(bytes); if (M_client != hash) { throw new SRP6SafeguardException("SRP6 could not validate proof 'K'."); } BigInteger M = Hash(A, M_client, K); Byte[] M_bytes = SRPHelpers.GetBytesFromBigInteger(M); //reverse byte SRPHelpers.ReverseBytesAsUInt32(M_bytes); serverKeyDataWriter.Write(M_bytes.Length); // 32 serverKeyDataWriter.Write(M_bytes, 0, M_bytes.Length); }
public BigInteger Hash(BigInteger integer) { sha256.Initialize(); Byte[] bytes = SRPHelpers.GetBytesFromBigInteger(integer); int padding = (4 - bytes.Length % 4) % 4; // if there's no need for padding just return a simple hash. if (padding == 0) { return(SRPHelpers.GetBigIntegerFromBytes(sha256.ComputeHash(bytes))); } sha256.TransformBlock(bytes, 0, bytes.Length, null, 0); sha256.TransformFinalBlock(s_bytesPadding[padding], 0, padding); // this doesnt seem to be inverted. return(SRPHelpers.GetBigIntegerFromBytes(sha256.Hash)); }
// TODO: Optimize this method private BigInteger HashKey(BigInteger key) { sha256.Initialize(); Byte[] output = new Byte[64]; Byte[] keyBytes = SRPHelpers.GetBytesFromBigInteger(key); Byte[] v13; Byte[] hash = new Byte[32]; Int32 keyLen = keyBytes.Length; Int32 len0 = keyLen; Int32 len; Int32 ptr0 = 0; if (keyLen > 4) { do { if (keyBytes[ptr0] == 0) { break; } len0--; ptr0++; }while (len0 > 4); } len = len0 >> 1; Int32 v6 = 0; v13 = new Byte[len]; if (len >> 1 != 0) { int v7 = len0 + ptr0 - 1; do { v13[v6++] = keyBytes[v7]; v7 -= 2; }while (v6 < len); } hash = sha256.ComputeHash(v13); // copy hash to output for (int i = 0; i < 32; i++) { output[i * 2] = hash[i]; } // make second part Int32 v9 = 0; if (len != 0) { Int32 v10 = len0 + ptr0 - 2; do { v13[v9++] = keyBytes[v10]; v10 -= 2; }while (v9 < len); } hash = sha256.ComputeHash(v13); // copy hash to output for (int i = 0; i < 32; i++) { output[i * 2 + 1] = hash[i]; } return(SRPHelpers.GetBigIntegerFromBytes(output)); }
private BigInteger MakeRandomBigInteger(Int32 bytes) { Byte[] r = new Byte[bytes]; rng.GetBytes(r); return(SRPHelpers.GetBigIntegerFromBytes(r) % N); }