{"record":{"id":"37779e8d257d2b08","repo":"jstedfast/MailKit","slug":"incorrecthash-challenge-contained-a-signature-with-an","errorCode":"IncorrectHash","errorMessage":"Challenge contained a signature with an invalid length.","messagePattern":"Challenge contained a signature with an invalid length\\.","errorType":"error_code","errorClass":"SaslException","httpStatus":null,"severity":"error","filePath":"MailKit/Security/SaslMechanismScramBase.cs","lineNumber":407,"sourceCode":"\n\t\t\t\tresponse = Encoding.UTF8.GetBytes (withoutProof + \",p=\" + Convert.ToBase64String (key));\n\t\t\t\tstate = LoginState.Validate;\n\t\t\t\tbreak;\n\t\t\tcase LoginState.Validate:\n\t\t\t\tif (token == null)\n\t\t\t\t\tthrow new SaslException (MechanismName, SaslErrorCode.MissingChallenge, \"Server response did not contain any authentication data.\");\n\n\t\t\t\tvar challenge = Encoding.UTF8.GetString (token, startIndex, length);\n\n\t\t\t\tif (!challenge.StartsWith (\"v=\", StringComparison.Ordinal))\n\t\t\t\t\tthrow new SaslException (MechanismName, SaslErrorCode.InvalidChallenge, \"Challenge did not start with a signature.\");\n\n\t\t\t\tsignature = Convert.FromBase64String (challenge.Substring (2));\n\t\t\t\tvar serverKey = HMAC (salted!, Encoding.ASCII.GetBytes (\"Server Key\"));\n\t\t\t\tvar calculated = HMAC (serverKey, auth!);\n\n\t\t\t\tif (signature.Length != calculated.Length)\n\t\t\t\t\tthrow new SaslException (MechanismName, SaslErrorCode.IncorrectHash, \"Challenge contained a signature with an invalid length.\");\n\n\t\t\t\tfor (int i = 0; i < signature.Length; i++) {\n\t\t\t\t\tif (signature[i] != calculated[i])\n\t\t\t\t\t\tthrow new SaslException (MechanismName, SaslErrorCode.IncorrectHash, $\"Challenge contained an invalid signature. Expected: {Convert.ToBase64String (calculated)}\");\n\t\t\t\t}\n\n\t\t\t\tnegotiatedChannelBinding = channelBindingKind != ChannelBindingKind.Unknown;\n\t\t\t\tIsAuthenticated = true;\n\t\t\t\tresponse = Array.Empty<byte> ();\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new IndexOutOfRangeException (\"state\");\n\t\t\t}\n\n\t\t\treturn response;\n\t\t}\n\n\t\t/// <summary>","sourceCodeStart":389,"sourceCodeEnd":425,"githubUrl":"https://github.com/jstedfast/MailKit/blob/9d3859a7855e3e17582c07fd01972b8e262bf176/MailKit/Security/SaslMechanismScramBase.cs#L389-L425","documentation":"The SCRAM server-final-message contained a 'v=' signature, but after base64-decoding it its byte length differs from the locally computed HMAC-based Server Signature length. SaslMechanismScramBase.Challenge throws SaslException with SaslErrorCode.IncorrectHash because a valid signature must match the hash output size of the negotiated SCRAM variant.","triggerScenarios":"Server returns 'v=' followed by base64 data whose decoded length does not equal the HMAC output size (20 bytes for SHA-1, 32 for SHA-256, 64 for SHA-512) — typically truncated or nonconformant server output.","commonSituations":"Proxy/gateway truncating the SASL payload, a server implementing a different SCRAM hash length than advertised in its mechanism name, or custom/buggy server SASL implementations.","solutions":["Capture the exchange with a protocol logger and base64-decode the 'v=' value to check its length against the mechanism's hash size.","Bypass proxies/SSL inspection that may mangle the SASL continuation.","Use a different mechanism (PLAIN/LOGIN over TLS) if the server's SCRAM implementation is nonconformant.","Report the bug to the server vendor or upgrade the server; also try a different MailKit version to rule out client-side issues."],"exampleFix":"// before\nclient.Authenticate (new SaslMechanismScramSha512 (credentials)); // server's SCRAM-SHA-512 is buggy\n// after\nclient.Authenticate (new SaslMechanismScramSha256 (credentials)); // known-good variant\n// or over TLS:\n// client.Authenticate (new SaslMechanismPlain (credentials));","handlingStrategy":"try-catch","validationCode":"// cannot be validated before the call; verify the server's advertised mechanism\n// matches its implementation (e.g. SCRAM-SHA-256 must emit a 32-byte signature)","typeGuard":"static bool HasExpectedSignatureLength (byte[] signature, string mechanismName) =>\n    mechanismName.Contains (\"SHA256\") ? signature.Length == 32\n    : mechanismName.Contains (\"SHA512\") ? signature.Length == 64\n    : signature.Length == 20;","tryCatchPattern":"try {\n    client.Authenticate (new SaslMechanismScramSha256 (credentials));\n} catch (SaslException ex) when (ex.ErrorCode == SaslErrorCode.IncorrectHash) {\n    logger.LogError (\"SCRAM signature length mismatch — server SASL implementation likely nonconformant\");\n    throw; // or fall back to another mechanism\n}","preventionTips":["Prefer well-known server implementations (Dovecot/Cyrus) with current versions","Bypass proxies or TLS inspection appliances that can truncate SASL frames","Pin the SCRAM variant to one the server demonstrably supports","Keep a fallback authentication mechanism configured over TLS"],"tags":["sasl","scram","signature","hash-length","mailkit"],"backgroundTag":"checksum-mismatch","analyzedSha":"9d3859a7855e3e17582c07fd01972b8e262bf176","analyzedAt":"2026-09-15T15:46:11.592Z","contentChangedAt":"2026-09-15T15:46:11.592Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}