Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/261.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#TLS 1.1的实施_C#_.net_Ssl_Handshake - Fatal编程技术网

C#TLS 1.1的实施

C#TLS 1.1的实施,c#,.net,ssl,handshake,C#,.net,Ssl,Handshake,一段时间以来,我一直在拼命尝试在我的应用程序中实现TLS1.1。这背后的原因是使用了SocketType.Raw套接字,因此没有SslStream或其他更高级别的类可供我使用 到目前为止,我还停留在TLS握手协议中已完成的消息上——继续在服务器响应中接收坏记录mac(20)。密码套件是0x0005-TLS\U RSA\U和\U RC4\U 128\U SHA 下面是一些关于发生了什么的示例代码: byte[] client_random, server_random = new byte

一段时间以来,我一直在拼命尝试在我的应用程序中实现TLS1.1。这背后的原因是使用了SocketType.Raw套接字,因此没有SslStream或其他更高级别的类可供我使用

到目前为止,我还停留在TLS握手协议中已完成的消息上——继续在服务器响应中接收坏记录mac(20)。密码套件是0x0005-TLS\U RSA\U和\U RC4\U 128\U SHA

下面是一些关于发生了什么的示例代码:

    byte[] client_random, server_random = new byte[28];
    byte[] pre_master_secret, master_secret;
    byte[] client_write_MAC_secret, server_write_MAC_secret, client_write_key, server_write_key;
    byte[] handshake_messages, verify_data;

    RSACryptoServiceProvider rsa;
    List<X509Certificate2> certificates = new List<X509Certificate2>();

    //certificates are added
    rsa = (RSACryptoServiceProvider)certificates.First().PublicKey.Key;

    private byte[] ClientKeyExchange()
    {
        pre_master_secret = new byte[48];
        (new Random()).NextBytes(pre_master_secret);

        //version 0302 for TLS 1.1
        pre_master_secret[0] = 3;
        pre_master_secret[1] = 2;

        byte[] cryptedData = rsa.Encrypt(pre_master_secret, false);
        //"1603020086"
        string tmp_string = "100000820080" + Utils.BitConverter.ToString(cryptedData).Replace("-", "");
        AddHandShakeData(Utils.BitConverter.StringToByteArray(tmp_string));
        tmp_string =
            "1603020086"
            + tmp_string
            + "140302000101" //Cipher Change Spec
            + "";

        return Utils.BitConverter.StringToByteArray(tmp_string);
    }

    private void ComputeMasterSecret()
    {
        byte[] label = Utils.BitConverter.StringToByteArray(Utils.BitConverter.ConvertStringToHex("master secret", Encoding.ASCII));

        byte[] seed = new byte[client_random.Length + server_random.Length];
        Buffer.BlockCopy(client_random, 0, seed, 0, client_random.Length);
        Buffer.BlockCopy(server_random, 0, seed, client_random.Length, server_random.Length);

        master_secret = PRF(pre_master_secret, label, seed, 48);
    }

    private void ComputeKeys()
    {
        byte[] label = Utils.BitConverter.StringToByteArray(Utils.BitConverter.ConvertStringToHex("key expansion", Encoding.ASCII));

        byte[] seed = new byte[client_random.Length + server_random.Length];
        Buffer.BlockCopy(client_random, 0, seed, 0, client_random.Length);
        Buffer.BlockCopy(server_random, 0, seed, client_random.Length, server_random.Length);

        byte[] key_material = PRF(master_secret, label, seed, 72);

        client_write_MAC_secret = new byte[20];
        Buffer.BlockCopy(key_material, 0, client_write_MAC_secret, 0, 20);
        server_write_MAC_secret = new byte[20];
        Buffer.BlockCopy(key_material, 20, server_write_MAC_secret, 0, 20);
        client_write_key = new byte[16];
        Buffer.BlockCopy(key_material, 40, client_write_key, 0, 16);
        server_write_key = new byte[16];
        Buffer.BlockCopy(key_material, 56, server_write_key, 0, 16);
    }

    private void ComputeVerifyData()
    {
        byte[] label = Utils.BitConverter.StringToByteArray(Utils.BitConverter.ConvertStringToHex("client finished", Encoding.ASCII));

        SHA1 sha1 = SHA1.Create();
        MD5 md5 = MD5.Create();
        md5.ComputeHash(handshake_messages);
        sha1.ComputeHash(handshake_messages);

        byte[] seed = new byte[md5.HashSize / 8 + sha1.HashSize / 8];
        Buffer.BlockCopy(md5.Hash, 0, seed, 0, md5.HashSize / 8);
        Buffer.BlockCopy(sha1.Hash, 0, seed, md5.HashSize / 8, sha1.HashSize / 8);

        verify_data = PRF(master_secret, label, seed, 12);
    }

    private byte[] PRF(byte[] secret, byte[] label, byte[] seed, int output_size)
    {
        int md5_iterations = (int)Math.Ceiling((double)output_size / 16),
            sha1_iterations = (int)Math.Ceiling((double)output_size / 20);

        byte[] md5_data = new byte[output_size],
               sha1_data = new byte[output_size];

        //особое колдунство для нечетного числа
        byte[] secret_1 = new byte[(int)Math.Ceiling((double)secret.Length / 2)],
               secret_2 = new byte[(int)Math.Ceiling((double)secret.Length / 2)];
        Buffer.BlockCopy(secret, 0, secret_1, 0, secret_1.Length);
        Buffer.BlockCopy(secret, secret.Length / 2, secret_2, 0, secret_2.Length);

        byte[] A = new byte[label.Length + seed.Length];
        Buffer.BlockCopy(label, 0, A, 0, label.Length);
        Buffer.BlockCopy(seed, 0, A, label.Length, seed.Length);

        byte[] tmp = new byte[md5_iterations * 16];

        //A(1) ?
        //A = P_MD5(secret_1, A);

        for (int i = 0; i < md5_iterations; i++)
        {
            A = P_MD5(secret_1, A);
            Buffer.BlockCopy(A, 0, tmp, i * A.Length, A.Length);
        }
        Buffer.BlockCopy(tmp, 0, md5_data, 0, md5_data.Length); //output_size = md5_data.Length

        tmp = new byte[sha1_iterations * 20];

        //does it have to start with A(1) ?
        //A = P_SHA1(secret_2, A);


        for (int i = 0; i < sha1_iterations; i++)
        {
            A = P_SHA1(secret_2, A);
            Buffer.BlockCopy(A, 0, tmp, i * A.Length, A.Length);
        }
        Buffer.BlockCopy(tmp, 0, sha1_data, 0, sha1_data.Length); //output_size = sha1_data.Length

        for (int i = 0; i < output_size; i++)
            md5_data[i] = (byte)(md5_data[i] ^ sha1_data[i]);

        return md5_data;
    }

    private byte[] P_MD5(byte[] secret /*это ключ?*/, byte[] seed /*это дата?*/)
    {
        HMACMD5 HMD5 = new HMACMD5(secret);
        HMD5.ComputeHash(seed);
        return HMD5.Hash;
    }

    private byte[] P_SHA1(byte[] secret /*это ключ?*/, byte[] seed /*это дата?*/)
    {
        HMACSHA1 HSHA1 = new HMACSHA1(secret);
        HSHA1.ComputeHash(seed);
        return HSHA1.Hash;
    }

    private byte[] MAC(byte[] secret, byte[] data)
    {
        byte[] secret_64 = new byte[64];
        Buffer.BlockCopy(secret, 0, secret_64, 0, secret.Length);

        for (int i = 0; i < 64; i++)
            secret_64[i] = (byte)(secret_64[i] ^ (byte)54);

        byte[] xor_output_data = new byte[64 + data.Length];
        Buffer.BlockCopy(secret_64, 0, xor_output_data, 0, 64);
        Buffer.BlockCopy(data, 0, xor_output_data, 64, data.Length);

        SHA1 sha1 = SHA1.Create();
        sha1.ComputeHash(xor_output_data);

        secret_64 = new byte[64];
        Buffer.BlockCopy(secret, 0, secret_64, 0, secret.Length);

        for (int i = 0; i < 64; i++)
            secret_64[i] = (byte)(secret_64[i] ^ (byte)92);

        xor_output_data = new byte[64 + sha1.HashSize / 8];
        Buffer.BlockCopy(secret_64, 0, xor_output_data, 0, 64);
        Buffer.BlockCopy(sha1.Hash, 0, xor_output_data, 64, sha1.HashSize / 8);

        sha1.ComputeHash(xor_output_data);

        return sha1.Hash;
    }

    public void RC4(ref Byte[] bytes, Byte[] key)
    {
        Byte[] s = new Byte[128];
        Byte[] k = new Byte[128];
        Byte temp;
        int i, j;

        for (i = 0; i < 128; i++)
        {
            s[i] = (Byte)i;
            k[i] = key[i % key.GetLength(0)];
        }

        j = 0;
        for (i = 0; i < 128; i++)
        {
            j = (j + s[i] + k[i]) % 128;
            temp = s[i];
            s[i] = s[j];
            s[j] = temp;
        }

        i = j = 0;
        for (int x = 0; x < bytes.GetLength(0); x++)
        {
            i = (i + 1) % 128;
            j = (j + s[i]) % 128;
            temp = s[i];
            s[i] = s[j];
            s[j] = temp;
            int t = (s[i] + s[j]) % 128;
            bytes[x] ^= s[t];
        }
    }
什么是种子?是我们计算散列的数据吗?秘密=钥匙,就我所知。另外,我们是否以(1)开始P_散列


提前谢谢

种子是客户端随机+服务器随机。您需要将它们从握手的前面步骤、客户机的hello和服务器的hello中保留下来

A(0) = seed 
A(i) = HMAC_hash(secret,A(i-1)) for i>0
函数的输出由一(1)、一(2)、一(3)

A(0) = seed 
A(i) = HMAC_hash(secret,A(i-1)) for i>0