{"record":{"id":"ff1e7d46fb8d2821","repo":"jstedfast/MailKit","slug":"the-machine-id-must-be-32-bytes","errorCode":null,"errorMessage":"The machine id must be 32 bytes.","messagePattern":"The machine id must be 32 bytes\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"MailKit/Security/Ntlm/NtlmSingleHostData.cs","lineNumber":85,"sourceCode":"\t\t/// </exception>\n\t\t/// <exception cref=\"ArgumentException\">\n\t\t/// <para><paramref name=\"customData\"/> is not 8 bytes.</para>\n\t\t/// <para>-or-</para>\n\t\t/// <para><paramref name=\"machineId\"/> is not 32 bytes.</para>\n\t\t/// </exception>\n\t\tpublic NtlmSingleHostData (byte[] customData, byte[] machineId)\n\t\t{\n\t\t\tif (customData == null)\n\t\t\t\tthrow new ArgumentNullException (nameof (customData));\n\n\t\t\tif (customData.Length != 8)\n\t\t\t\tthrow new ArgumentException (\"The custom data must be 8 bytes.\", nameof (customData));\n\n\t\t\tif (machineId == null)\n\t\t\t\tthrow new ArgumentNullException (nameof (machineId));\n\n\t\t\tif (machineId.Length != 32)\n\t\t\t\tthrow new ArgumentException (\"The machine id must be 32 bytes.\", nameof (machineId));\n\n\t\t\tCustomData = customData;\n\t\t\tMachineId = machineId;\n\t\t\tSize = 48;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// Get or set an 8-byte platform-specific blob.\n\t\t/// </summary>\n\t\t/// <remarks>\n\t\t/// Gets or sets an 8-byte platform-specific blob.\n\t\t/// </remarks>\n\t\tpublic byte[] CustomData {\n\t\t\tget; private set;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// Get the 256-bit randomly generated machine ID.","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/jstedfast/MailKit/blob/9d3859a7855e3e17582c07fd01972b8e262bf176/MailKit/Security/Ntlm/NtlmSingleHostData.cs#L67-L103","documentation":"The NtlmSingleHostData constructor throws ArgumentException when machineId is not exactly 32 bytes. The MachineID field in NTLM Single_Host_Data is a fixed 32-byte value, so any other length is rejected. This keeps the encoded structure a well-formed 48 bytes.","triggerScenarios":"Calling new NtlmSingleHostData(customData, machineId) with machineId.Length != 32 — e.g. passing a SHA-1 hash (20 bytes), a GUID (16 bytes), or an over-long buffer slice.","commonSituations":"Using a different hash algorithm output as the machine ID; swapping the 8-byte customData and 32-byte machineId arguments; slicing the blob with wrong offsets so the tail got merged into the machine ID.","solutions":["Pass exactly 32 bytes for machineId (e.g. HMAC-SHA256 output or the decoded 32-byte field)","Check the argument order: customData (8 bytes) first, machineId (32 bytes) second","Verify offsets when slicing a 48-byte Single_Host_Data blob"],"exampleFix":"// before\nvar machineId = sha1.ComputeHash(data); // 20 bytes\nnew NtlmSingleHostData(customData, machineId);\n// after\nvar machineId = hmacSha256.ComputeHash(data); // 32 bytes\nnew NtlmSingleHostData(customData, machineId);","handlingStrategy":"type-guard","validationCode":"if (machineId is null || machineId.Length != 32)\n    throw new ArgumentException(\"machineId must be exactly 32 bytes\");","typeGuard":"static bool Is32Bytes(byte[] m) => m is { Length: 32 };","tryCatchPattern":"try { var d = new NtlmSingleHostData(customData, machineId); }\ncatch (ArgumentException ex) when (ex.ParamName == \"machineId\") { /* use a proper 32-byte hash */ }","preventionTips":["Use a 256-bit hash/HMAC (e.g. HMAC-SHA256) for machine IDs","Keep argument order straight: customData(8) then machineId(32)","Add length assertions where blobs are sliced"],"tags":["ntlm","argument-length","mailkit"],"backgroundTag":"invalid-argument-value","analyzedSha":"9d3859a7855e3e17582c07fd01972b8e262bf176","analyzedAt":"2026-09-15T15:46:11.592Z","contentChangedAt":"2026-09-15T15:46:11.592Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}