同一密钥下Java与.NET 4.6生成JWE令牌不一致,求.NET端解决方案
Let’s start with a key clarification: it’s totally normal for JWE tokens generated with identical inputs to have different string values. JWE uses random initialization vectors (IVs) and encrypted content encryption keys (CEKs) every time you generate a token, so the raw string will vary. The real problem to solve is whether the tokens can be decrypted across platforms. If you’re seeing cross-decryption failures, here’s how to adjust your .NET code, plus alternative libraries compatible with .NET 4.6.
Fixes for Your jose-jwt Implementation
There are a few subtle differences between Nimbus JOSE and jose-jwt that could break compatibility:
1. Explicitly Align Header Parameters
While jose-jwt should automatically add alg and enc headers based on your method arguments, explicitly defining them ensures full alignment with Nimbus’s header structure:
string payload = "{\"testP\":\"test\"}"; var headers = new Dictionary<string, object> { {"kid", "test_kid"}, {"alg", "A256KW"}, // Match Nimbus's key wrap algorithm {"enc", "A256GCM"} // Match Nimbus's content encryption method }; byte[] secretKey = <your 32-byte secret key bytes>; var jweToken = JWT.Encode(payload, secretKey, JweAlgorithm.A256KW, JweEncryption.A256GCM, extraHeaders: headers);
2. Verify Key Byte Consistency
Double-check that your .NET secretKey byte array is exactly the same as the key in Java. For example, if your key comes from a string:
- In Java: Use
key.getBytes(StandardCharsets.UTF_8) - In .NET: Use
Encoding.UTF8.GetBytes(key)
Never mix encodings (like using Unicode in .NET) as this will produce mismatched key bytes.
3. Confirm Key Length for A256KW
A256KW requires a 256-bit (32-byte) key. If your key is shorter, Nimbus and jose-jwt may handle padding/derivation differently, leading to decryption failures. Ensure your key is exactly 32 bytes long.
Alternative .NET 4.6-Compatible JWE Libraries
If jose-jwt still has compatibility issues, these libraries are reliable and well-supported for .NET 4.6:
1. Microsoft.IdentityModel.Tokens (Official Microsoft Library)
This is the most robust, enterprise-grade library for JWT/JWE in .NET. Here’s a quick example to generate your JWE:
using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; string payload = "{\"testP\":\"test\"}"; byte[] secretKey = <your 32-byte key>; var securityKey = new SymmetricSecurityKey(secretKey); // Build header with kid and required algorithms var header = new JwtHeader(new SigningCredentials(securityKey, SecurityAlgorithms.Aes256KW)) { {"kid", "test_kid"} }; header.Add("enc", SecurityAlgorithms.Aes256Gcm); // Parse payload and create token var payloadObj = JwtPayload.Deserialize(payload); var jwtToken = new JwtSecurityToken(header, payloadObj); // Serialize to JWE string var handler = new JwtSecurityTokenHandler(); string jweToken = handler.WriteToken(jwtToken);
2. IdentityModel
A lightweight, developer-friendly library that simplifies JWT/JWE operations. It wraps lower-level cryptography APIs and offers great cross-platform compatibility, including .NET 4.6.
3. BouncyCastle
While not a dedicated JWT library, BouncyCastle provides comprehensive cryptography primitives to implement JWE manually. It’s a good choice if you need full control over the encryption process, though it requires more boilerplate code.
内容的提问来源于stack exchange,提问作者Nilmi Nawalage

