如何解密半径PEAP协议客户终止握手消息



我正在使用tls_rsa_with_with_3des_ede_ede_ce_cbc_sha cipher suite for the radius服务器,收到了一条加密的握手消息(40个字节)(40个字节),changecipherspec之后,changecipherspec从clangecipherspec中使用了客户,我曾尝试将3des与cbc Mode decranderpt使用。字节,但除了例外(不良数据),试图在https://www.rfc-editor.org/rfc/rfc/rfc2246上查找PEAP TLS v1.0详细的握手加密/解密。任何帮助都会很棒,非常感谢!

这是我用来计算主秘密和关键材料的代码。

    public static byte[] ComputeMasterSecret(byte[] pre_master_secret, byte[] client_random, byte[] server_random)
    {
        byte[] label = Encoding.ASCII.GetBytes("master secret");
        var seed = new List<byte>();
        seed.AddRange(client_random);
        seed.AddRange(server_random);
        var master_secret = PRF(pre_master_secret, label, seed.ToArray(), 48);
        return master_secret;
    }
    public static KeyMaterial ComputeKeys(byte[] master_secret, byte[] client_random, byte[] server_random)
    {
        /*
         * The cipher spec which is defined in this document which requires
        the most material is 3DES_EDE_CBC_SHA: it requires 2 x 24 byte
        keys, 2 x 20 byte MAC secrets, and 2 x 8 byte IVs, for a total of
 
        104 bytes of key material.
        */
 
        byte[] label = Encoding.ASCII.GetBytes("key expansion");
        var seed = new List<byte>();
        seed.AddRange(client_random);
        seed.AddRange(server_random);
        byte[] key_material = PRF(master_secret, label, seed.ToArray(), 104);  //need 104 for TLS_RSA_WITH_3DES_EDE_CBC_SHA cipher suite

        var km = new KeyMaterial();
        int idx = 0;
        km.ClientWriteMACSecret = Utils.CopyArray(key_material, idx, 20);
        idx += 20;
        km.ServerWriteMACSecret = Utils.CopyArray(key_material, idx, 20);
        idx += 20;
        km.ClientWriteKey = Utils.CopyArray(key_material, idx, 24);
        idx += 24;
        km.ServerWriteKey = Utils.CopyArray(key_material, idx, 24);
        idx += 24;
        km.ClientWriteIV = Utils.CopyArray(key_material, idx, 8);
        idx += 8;
        km.ServerWriteIV = Utils.CopyArray(key_material, idx, 8);
        return km;
    }
    public static byte[] PRF(byte[] secret, byte[] label, byte[] seed, int outputLength)
    {
        List<byte> s1 = new List<byte>();
        List<byte> s2 = new List<byte>();
        int size = (int)Math.Ceiling((double)secret.Length / 2);
        
        for(int i=0;i < size; i++)
        {
            s1.Add(secret[i]);
            s2.Insert(0, secret[secret.Length - i - 1]);
        }
        var tbc = new List<byte>();
        tbc.AddRange(label);
        tbc.AddRange(seed);
        var md5Result = MD5Hash(s1.ToArray(), tbc.ToArray(), outputLength);
        var sha1Result = SHA1Hash(s2.ToArray(), tbc.ToArray(), outputLength);
        
        var result = new List<byte>();
        for (int i = 0; i < outputLength; i++)
            result.Add((byte)(md5Result[i] ^ sha1Result[i]));
        return result.ToArray();
    }
    /// <summary>
    /// P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
    ///                        HMAC_hash(secret, A(2) + seed) +
    ///                        HMAC_hash(secret, A(3) + seed) + ...
    /// Where + indicates concatenation.
    ///  A() is defined as:
    /// A(0) = seed
    /// A(i) = HMAC_hash(secret, A(i-1))
    /// </summary>
    /// <param name="secret"></param>
    /// <param name="seed"></param>
    /// <param name="iterations"></param>
    /// <returns></returns>
    private static byte[] MD5Hash(byte[] secret, byte[] seed, int outputLength)
    {
        int iterations = (int)Math.Ceiling((double)outputLength / 16);
        HMACMD5 HMD5 = new HMACMD5(secret);
        var result = new List<byte>();
        byte[] A = null;
        for (int i = 0; i <= iterations; i++)
            if (A == null)
                A = seed;
            else
            {
                A = HMD5.ComputeHash(A);
                var tBuff = new List<byte>();
                tBuff.AddRange(A);
                tBuff.AddRange(seed);
                var tb = HMD5.ComputeHash(tBuff.ToArray());
                result.AddRange(tb);
            }
        return result.ToArray();
    }
    private static byte[] SHA1Hash(byte[] secret, byte[] seed, int outputLength)
    {
        int iterations = (int)Math.Ceiling((double)outputLength / 20);
        HMACSHA1 HSHA1 = new HMACSHA1(secret);
        var result = new List<byte>();
        byte[] A = null;
        for (int i = 0; i <= iterations; i++)
            if (A == null)
                A = seed;
            else
            {
                A = HSHA1.ComputeHash(A);
                var tBuff = new List<byte>();
                tBuff.AddRange(A);
                tBuff.AddRange(seed);
                var tb = HSHA1.ComputeHash(tBuff.ToArray());
                result.AddRange(tb);
            }
        return result.ToArray();
    }

包含成品握手消息的记录的身份验证/加密和解密/验证与SSL/TLS中的所有其他记录相同,只是它是CCS之后的第一个。

首先(在握手期间),根据套件的不同,钥匙扣汇出的主机秘密用于得出主秘密和多个工作密钥和IV。这与协议版本有所不同。对于TLS1.0,请参见RFC2246第8.1.1节(对于平原RSA)6.3(对于所有KeyExchanges)和5。

使用'genericblock'(CBC)密码 - 这是TLS1.0和1.1中的RC4以外的唯一选项 - 使用6.2.3.1片段化(此记录不需要)6.2.3.3 6.2.3.2可选压缩(通常不使用如今,由于犯罪之类的攻击,无论如何EAP流量毫无用处)和6.2.3.2。

特别是,首先添加了HMAC(对于此Suite HMAC-SHA1),然后添加填充,然后使用数据密码(3DES-CBC)加密结果,该iv使用IV进行IV从上方的密钥派生步骤中,对于后续记录,来自上一个记录的最后一个块。(后者是罗加威(Rogaway)首次报道的缺陷,并由野兽剥削。)

解密和验证以明显的方式逆转了此过程。注意RFC2246未指定接收器必须检查所有填充字节,但这显然是故意的。RFC4346(1.1)确实指定了它,而无需更改内容。(rfc4346 die 更改静脉处理以修复rogaway缺陷。sslv3指定的随机填充除了最终的长度字节,因此检查了无法检查。这是poodle缺陷。)

一些为块密码(包括3DE)提供CBC模式的库/API,用于默认为PKCS5/7填充的任意数据。填充TLS的用途类似于但与PKCS5/7填充不兼容,因此使用这些库,您可能必须按照6.2.3.2中的说明处理填充并取消自己的填充 - 或大约十二个OpenSource tls tls实现中的代码。

相关内容

  • 没有找到相关文章