2017-12-26 9 views
0

クライアントからChangeCipherSpecの直後に暗号化ハンドシェイクメッセージ(40バイト)を受け取ったTLS_RSA_WITH_3DES_EDE_CBC_SHA暗号スイートをradiusサーバに使用しています.cdescモードで3desを使用しようとしましたこれらのバイトを復号化しますが、例外(不良データ)を使用して、https://tools.ietf.org/html/rfc2246のpeap tls v1.0を検索しようとしましたが、仕上げハンドシェイクの暗号化/復号化に関する詳細が詳細に見つかりませんでした。どんな助けも素晴らしいでしょう、ありがとう!radius peapプロトコルクライアントの終了ハンドシェイクメッセージを解読する方法

ここには、私がマスターシークレットと主要資料を計算するために使用したコードがあります。

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(); 
    } 

答えて

1

完成握手メッセージを含むレコードの認証/暗号化と復号化/検証は、それはCCS後の最初であることを除いて、SSL/TLSのすべての他のレコードと同じです。

最初に(ハンドシェーク中)、keyexchangeからのpremaster secretを使用して、スイートに応じて、複数のワーキングキーとIVを取得します。これはプロトコルのバージョンによって少し異なります。 TLS1.0ではRC4以外の唯一のオプションであるrfc2246セクション8.1.1(すべての鍵交換用)6.3と(すべての鍵交換用)と5を参照してください。

C GenericBlock 6.2.3.2オプションの圧縮(現在のところCRIMEのような攻撃のために使用されず、とにかくEAPトラフィックではかなり役に立たない)6.2.3.2フラグメンテーション(このレコードには必要ない)6.2.3.2。

具体的には、最初にHMACが追加され(HMAC-SHA1スイートの場合)、パディングが行われ、その結果が、最初のレコード(完成品)のIVを持つデータ暗号(3DES-CBC)上記のキー導出ステップから来ており、後続のレコードは前のレコードの最後のブロックから得られます。 (後者は、Rogawayが最初に報告し、BEASTによって悪用された欠陥です。)

復号化と検証では、このプロセスが明らかに逆転します。 rfc2246では、受信者がパディングのすべてのバイトをチェックしなければならないと指定していませんが、これは明らかです。 rfc4346(1.1)は内容を変更することなくそれを指定します。 (RFC4346 はRogawayの欠陥を修正するための変更IVの取り扱いを行うのSSLv3は、最終長さバイト以外のランダムなパディングをそのようがチェックすることはできません指定された;これは、POODLE欠陥れる。)/いくつかのライブラリ

を任意のデータのデフォルトのブロック暗号(3DESを含む)に対してCBCモードを提供するAPIがPKCS5/7パディングにデフォルト設定されています。パッディングTLSはPKCS5/7パッディングと似ていますが、PKCS5/7パッディングと互換性がありません。これらのライブラリを使用すると、6.2.3.2の指示に従ったパディングやアンパック処理が必要になることがあります。

+0

上記の関数でマスターキーとキーマテリアルを計算しました.C#を使用していますが、PCKS7と互換性のあるドットネットからTripleDESクラスをチェックしました。 TLSはPKCS5/7と互換性がないため、パディングとアンパックを処理した後、これらの40バイトを復号化できるはずです。 – YanXi

+0

@YanXi:私はdotNETの経験は個人的には持っていませんが、これも期待しています。 –

+0

もう一度ありがとう、パディングはデータ処理を暗号化する前に行うべきではありませんか?だから私は何もせずにデータを解読することはできませんか?暗号化プロセスの後に別のパディングが必要な場合は、3DES-CBCのパディングとアンパインドの方法についての情報はありますか? – YanXi

関連する問題