You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AES GCM从Python到C#移植问题:GHASH计算与Wireshark不匹配

Troubleshooting GHASH Auth Tag Mismatch in AES-GCM C# Port

Hey there, let's dig into this GHASH issue you're facing with your AES-GCM port from Python to C#. Since you've confirmed that GF_mult and standalone GHASH calculations match between the two languages, but the final auth_tag doesn't align with Wireshark (and your TLS handshake fails), here are targeted areas to investigate:

1. Validate GHASH Input Padding & Formatting

AES-GCM strictly defines the input to GHASH as:

  • Padded AAD (auth_data): zero-padded to the next 128-bit (16-byte) boundary
  • Padded ciphertext: zero-padded to the next 128-bit boundary
  • A 128-bit block containing the big-endian 64-bit length of AAD (in bits) concatenated with the big-endian 64-bit length of ciphertext (in bits)

Double-check your C# code for these common mistakes:

  • Are you using zero-padding (not another padding scheme) for AAD and ciphertext?
  • Are the length fields encoded as big-endian? C# uses little-endian by default for primitives, so you'll need to reverse bytes if BitConverter.IsLittleEndian is true.
  • Are you including all parts of the input (no truncated blocks or extra added bytes)?

2. Verify GHASH Initialization Vector (X₀)

The initial GHASH state X₀ is derived from the GCM nonce (standard 96-bit nonce in TLS):
X₀ = nonce || 0x00000000 || 0x00000001 (all in big-endian)

Check these details in your code:

  • Is X₀ constructed correctly, especially the trailing 64-bit value (0x0000000000000001 as big-endian bytes)?
  • Are you treating the nonce as big-endian when building X₀ (no byte reversal errors)?

3. Confirm Block Processing Order & Logic

GHASH processes each 128-bit block sequentially with this formula:
Xᵢ = (Xᵢ₋₁ XOR blockᵢ) * H (where * is GF(2¹²⁸) multiplication via your GF_mult function)

Even if GF_mult works, verify:

  • Are you processing AAD blocks first, then ciphertext blocks, then the final length block (in that exact order)?
  • Are you applying the XOR with the previous state before multiplying by H (not the reverse)?
  • Are you skipping any blocks in the sequence?

4. Check Final Auth Tag Derivation

The auth tag is calculated as:
auth_tag = Xₙ XOR X₀ (where Xₙ is the final GHASH state after all blocks are processed)

Ensure:

  • You're XORing the final GHASH result with the original X₀ (not a modified version)
  • You're truncating the tag to the correct length (TLS typically uses 16-byte tags; avoid accidental shorter lengths)
  • There's no byte order mismatch in the final XOR step

5. Enforce Endianness Consistency

Endianness is a frequent culprit in crypto porting:

  • Always explicitly handle big-endian encoding when converting between byte arrays and numeric values (like length fields or GHASH state blocks)
  • For example, when converting a 64-bit length to bytes, use BitConverter.GetBytes(length).Reverse() if running on a little-endian system

6. Test with NIST Standard Vectors

Use official AES-GCM test vectors from NIST SP 800-38D to validate your full pipeline:

  • Pick a vector with known nonce, AAD, plaintext, key, expected ciphertext, and auth tag
  • Run your C# code against it: if the tag matches, the issue is TLS-specific (e.g., incorrect AAD formatting for TLS records). If not, compare intermediate GHASH states with your Python code to pinpoint the failing step

Quick Sanity Check

Since your standalone GHASH tests pass, have you tested with the exact input bytes Wireshark shows (including padded AAD, ciphertext, and length block)? It's possible your test case doesn't replicate the real TLS handshake input.


内容的提问来源于stack exchange,提问作者frenzy man

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:42:46