9

暗号を使用しているTLS 1.2セッションを復号化する Java プログラムに取り組んでいますTLS_RSA_WITH_AES_128_GCM_SHA256。Wireshark を使用してテスト セッションを記録しました。マスターシークレットが判明。

No.     Time           Protocol Length Info
      4 0.000124000    TLSv1.2  166    Client Hello
      6 0.000202000    TLSv1.2  1074   Server Hello, Certificate, Server Hello Done
      8 0.001071000    TLSv1.2  393    Client Key Exchange, Change Cipher Spec, Finished
      9 0.003714000    TLSv1.2  301    New Session Ticket, Change Cipher Spec, Finished
     11 6.443056000    TLSv1.2  116    Application Data
     12 6.443245000    TLSv1.2  765    Application Data
     15 6.443390000    TLSv1.2  103    Alert (Level: Warning, Description: Close Notify)

Packet 11HTTP GET Request 復号化しようとしているが含まれています。

握手データ:

Cipher:        TLS_RSA_WITH_AES_128_GCM_SHA256
Client Random: 375f5632ba9075b88dd83eeeed4adb427d4011298efb79fb2bf78f4a4b7d9d95
Server Random: 5a1b3957e3bd1644e7083e25c64f137ed2803b680e43395a82e5b302b64ba763    
Master Secret: 2FB179AB70CD4CA2C1285B4B1E294F8F44B7E8DA26B62D00EE35181575EAB04C
           4FA11C0DA3ABABB4AF8D09ACB4CCC3CD

パケット 11 データ:

Direction is Client -> Server.
Secure Sockets Layer
    TLSv1.2 Record Layer: Application Data Protocol: Application Data
    Content Type: Application Data (23)
    Version: TLS 1.2 (0x0303)
    Length: 45
    Encrypted Application Data: c91de005e2ae50a8a57abee55c183667b136343feef4a387cb7cf83030a47e230af268378c4f33c8b5bab3d26d

私がこれまでに行ったこと:

キーの派生:

Client->Server パッケージを復号化したいので、ここでは Client キーのみが必要です。サーバーとクライアントのキーと IV を RFC に従って拡張しました。 Client Write Key: 4B119DFBFC930ABE130030BD53C3BF78 Client Write IV: 2029CAE2

ノンス:

Salt (= Client Write IV) と明示的なナンス (= 暗号化されたデータの最初の 8 バイト) から AES-GCM ノンスを作成します。 Salt: 2029CAE2 explicitNonce: C91DE005E2AE50A8 Nonce: 2029CAE2C91DE005E2AE50A8

追加の認証データ (AAD):

これはどうやら私が行き詰まったところです。RFC5246 は次のように述べています。

additional_data = seq_num + TLSCompressed.type + TLSCompressed.version + TLSCompressed.length; ここで、「+」は連結を示します。

だから私はこれを作った:

byte[] aad = {0, 0, 0, 0, 0, 0, 0, 1,   // seq_no uint64
    0x17,               // type 0x17 = Application Data
    0x03, 0x03,             //  TLS Version 1.2
    0, 45};             // 45 Bytes of encrypted data

1だと思います。レコードが送信seq_noされると、ゼロにリセットされます。Change Cipher Spec( Packet #8) 次に、暗号化されたFinishedレコードにはseq_no = 0. 次のクライアント パケットはPacket #11 withseq_no = 1です。

コード:

今、すべてを BouncyCastle にフィードしています。

AEADParameters parameters = new AEADParameters(new KeyParameter(clientWriteKey), 128, nonce, aad);
GCMBlockCipher gcmBlockCipher = new GCMBlockCipher(new AESFastEngine());
gcmBlockCipher.init(false, parameters);
byte[] plainText = new byte[gcmBlockCipher.getOutputSize(cipherText.length)];
try {
    int decLen = gcmBlockCipher.processBytes(cipherText, 0, cipherText.length, plainText, 0);
    decLen += gcmBlockCipher.doFinal(plainText, decLen);
} catch (InvalidCipherTextException e) {
    System.out.println("MAC failed: " + e.getMessage());
}

これは常にMAC failed: mac check in GCM failedをスローします。しかし、復号化された出力は正しいです:

byte[] decomp = decompress(plainText);
System.out.println(new String(decomp, "UTF-8"));

これは印刷されGET / HTTP/1.0\nます。

解凍ヘルパー:

public static byte[] decompress(byte[] data) throws IOException, DataFormatException {
    Inflater inflater = new Inflater(true);
    inflater.setInput(data);

    ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
    byte[] buffer = new byte[1024];
    while (inflater.getRemaining() > 0) {
        int count = inflater.inflate(buffer);
        outputStream.write(buffer, 0, count);
    }
    outputStream.close();
    byte[] output = outputStream.toByteArray();

    inflater.end();
    return output;
    }

結論: 復号化された出力は正しいので、鍵の導出と復号化が正常に機能していると安全に想定できます。認証のみが失敗します。したがって、追加の認証データ (AAD) で何か問題が発生している可能性があります。したがって、この質問は次のように要約されます。

追加認証データ (AAD) はどのように正しく組み立てられますか?

ありがとうございました!

4

1 に答える 1