コード例 #1
0
        public static byte[] Expand(string hashName, byte[] secret, byte[] seed, int length)
        {
            HMAC hmac;

            switch (hashName)
            {
            case "MD5":
                hmac = new HMACMD5(secret);
                break;

            case "SHA1":
                hmac = new HMACSHA1(secret);
                break;

            case "SHA384":
                hmac = new HMACSHA384(secret);
                break;

            case "SHA512":
                hmac = new HMACSHA512(secret);
                break;

            default:     // SHA256
                hmac = new HMACSHA256(secret);
                break;
            }

            int hashLength = hmac.HashSize >> 3; // length in bytes
            int iterations = (int)(length / hashLength);

            if ((length % hashLength) > 0)
            {
                iterations++;
            }

            TlsStream resMacs = new TlsStream();

            byte[][] hmacs = new byte[iterations + 1][];
            hmacs[0] = seed;
            for (int i = 1; i <= iterations; i++)
            {
                TlsStream hcseed = new TlsStream();
                hmac.ComputeHash(hmacs[i - 1], 0, hmacs[i - 1].Length);
                hmacs[i] = hmac.Hash;
                hcseed.Write(hmacs[i]);
                hcseed.Write(seed);
                hmac.ComputeHash(hcseed.ToArray(), 0, (int)hcseed.Length);
                resMacs.Write(hmac.Hash);
                hcseed.Reset();
            }

            byte[] res = new byte[length];

            Buffer.BlockCopy(resMacs.ToArray(), 0, res, 0, res.Length);

            resMacs.Reset();

            return(res);
        }
コード例 #2
0
        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);
        }