public static byte[] PRF(byte[] secret, string label, byte[] data, int length, string tls, string sha) { /* Secret Length calc exmplain from the RFC2246. Section 5 * * S1 and S2 are the two halves of the secret and each is the same * length. S1 is taken from the first half of the secret, S2 from the * second half. Their length is created by rounding up the length of the * overall secret divided by two; thus, if the original secret is an odd * number of bytes long, the last byte of S1 will be the same as the * first byte of S2. */ // split secret in 2 int secretLen = secret.Length >> 1; // rounding up if ((secret.Length & 0x1) == 0x1) { secretLen++; } // Seed TlsStream seedStream = new TlsStream(); seedStream.Write(Encoding.ASCII.GetBytes(label)); seedStream.Write(data); byte[] seed = seedStream.ToArray(); seedStream.Reset(); byte[] masterSecret; if ("TLS1.2".Equals(tls, StringComparison.OrdinalIgnoreCase)) { masterSecret = Expand("SHA" + sha, secret, seed, length); } else { // Secret 1 byte[] secret1 = new byte[secretLen]; Buffer.BlockCopy(secret, 0, secret1, 0, secretLen); // Secret2 byte[] secret2 = new byte[secretLen]; Buffer.BlockCopy(secret, (secret.Length - secretLen), secret2, 0, secretLen); // Secret 1 processing byte[] p_md5 = Expand("MD5", secret1, seed, length); // Secret 2 processing byte[] p_sha = Expand("SHA1", secret2, seed, length); // Perfor XOR of both results masterSecret = new byte[length]; for (int i = 0; i < masterSecret.Length; i++) { masterSecret[i] = (byte)(p_md5[i] ^ p_sha[i]); } } return(masterSecret); }