JeffreySu/WeiXinMPSDK · error · CryptographicException
通知资源密文长度无效。
Error message
通知资源密文长度无效。
What it means
The Base64-decoded ciphertext must be longer than the 16-byte GCM authentication tag so it can be split into ciphertext + tag. A payload of 16 bytes or fewer cannot contain any plaintext plus a tag, so the library throws CryptographicException before attempting decryption.
Solutions
- Re-read the original webhook body and confirm resource.ciphertext is complete and valid Base64
- Check nothing is truncating the payload (proxy, logging middleware, fixed-size buffers)
- Validate decrypted length > 16 before calling DecryptResource in defensive wrappers
Example fix
// before
var plain = message.DecryptResource(aesKey);
// after
var raw = Convert.FromBase64String(message.Resource.ciphertext);
if (raw.Length <= 16)
throw new InvalidDataException($"ciphertext too short: {raw.Length} bytes");
var plain = message.DecryptResource(aesKey); Defensive patterns
Strategy: validation
Validate before calling
byte[] raw;
if (!Convert.TryFromBase64String(message.Resource?.ciphertext ?? "", raw = new byte[512], out var n) || n <= 16)
throw new InvalidDataException("ciphertext missing or too short"); Type guard
static bool HasValidCiphertext(Models.MessageEvent.Resource r) =>
r?.ciphertext != null && Convert.FromBase64String(r.ciphertext).Length > 16; Try / catch
try { var plain = msg.DecryptResource(aesKey); }
catch (CryptographicException ex) { log.Error("Bad ciphertext payload", ex); return Results.StatusCode(400); } Prevention
- Never truncate/re-encode webhook bodies when logging or replaying them
- Preserve the raw body bytes end-to-end through proxies and middleware
- Validate Base64 decodability of resource.ciphertext at the webhook boundary
When it happens
Trigger: resource.ciphertext decodes to <= 16 bytes — e.g. empty ciphertext, a truncated field, or the caller passing the tag-only portion.
Common situations: Corrupt/truncated webhook bodies logged and replayed incorrectly, encoding the ciphertext as a placeholder in tests, or manually slicing the encrypted buffer at the wrong offset.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- 通知中不包含 resource 节点。
- Invalid hex length for uncompressed EC public key
- 证书中未包含 RSA 公钥。
- 证书中未包含 RSA 公钥。
- 当前目标框架不提供 AES-GCM。请在 netstandard2.1、netcoreapp3.1…
AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12).
Data as JSON: /api/errors/70ba8c2bb7f2fe3a.
Report an issue: GitHub.
Appendix: source
Thrown at src/Senparc.Weixin.Work/Senparc.Weixin.Work/Entities/Request/Event/RequestMessageEvent_MiniProgramPay.cs:90
throw new ArgumentException("EncodingAESKey 必须为 43 个字符。", nameof(encodingAesKey));
}
if (resource == null)
{
throw new InvalidOperationException("通知中不包含 resource 节点。");
}
if (!string.Equals(resource.algorithm, "AEAD_AES_256_GCM", StringComparison.OrdinalIgnoreCase))
{
throw new NotSupportedException($"不支持的通知资源加密算法:{resource.algorithm}");
}
var key = Convert.FromBase64String(encodingAesKey + "=");
var encrypted = Convert.FromBase64String(resource.ciphertext);
const int tagSize = 16;
if (encrypted.Length <= tagSize)
{
throw new CryptographicException("通知资源密文长度无效。");
}
var ciphertext = new byte[encrypted.Length - tagSize];
var tag = new byte[tagSize];
var plaintext = new byte[ciphertext.Length];
Buffer.BlockCopy(encrypted, 0, ciphertext, 0, ciphertext.Length);
Buffer.BlockCopy(encrypted, ciphertext.Length, tag, 0, tag.Length);
try
{
var nonce = Encoding.UTF8.GetBytes(resource.nonce);
var associatedData = Encoding.UTF8.GetBytes(resource.associated_data ?? string.Empty);
#if NET8_0_OR_GREATER
using (var aesGcm = new AesGcm(key, tagSize))
#else
using (var aesGcm = new AesGcm(key))
#endif
{View on GitHub (pinned to be573f6f94)