{"record":{"id":"bc6c469ddb347119","repo":"shadowsocks/shadowsocks-windows","slug":"failed-to-generate-session-key","errorCode":null,"errorMessage":"failed to generate session key","messagePattern":"failed to generate session key","errorType":"exception","errorClass":"System.Exception","httpStatus":null,"severity":"critical","filePath":"shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs","lineNumber":124,"sourceCode":"                {\r\n                    md5sum = MbedTLS.MD5(password);\r\n                }\r\n                else\r\n                {\r\n                    Array.Copy(md5sum, 0, result, 0, MD5_LEN);\r\n                    Array.Copy(password, 0, result, MD5_LEN, password.Length);\r\n                    md5sum = MbedTLS.MD5(result);\r\n                }\r\n                Array.Copy(md5sum, 0, key, i, Math.Min(MD5_LEN, keylen - i));\r\n                i += MD5_LEN;\r\n            }\r\n        }\r\n\r\n        public void DeriveSessionKey(byte[] salt, byte[] masterKey, byte[] sessionKey)\r\n        {\r\n            int ret = MbedTLS.hkdf(salt, saltLen, masterKey, keyLen, InfoBytes, InfoBytes.Length, sessionKey,\r\n                keyLen);\r\n            if (ret != 0) throw new System.Exception(\"failed to generate session key\");\r\n        }\r\n\r\n        protected void IncrementNonce(bool isEncrypt)\r\n        {\r\n            lock (_nonceIncrementLock) {\r\n                Sodium.sodium_increment(isEncrypt ? _encNonce : _decNonce, nonceLen);\r\n            }\r\n        }\r\n\r\n        public virtual void InitCipher(byte[] salt, bool isEncrypt, bool isUdp)\r\n        {\r\n            if (isEncrypt) {\r\n                _encryptSalt = new byte[saltLen];\r\n                Array.Copy(salt, _encryptSalt, saltLen);\r\n            } else {\r\n                _decryptSalt = new byte[saltLen];\r\n                Array.Copy(salt, _decryptSalt, saltLen);\r\n            }\r","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/shadowsocks/shadowsocks-windows/blob/891d971682eefcaa2e640258d3b352a3ad3b2233/shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs#L106-L142","documentation":"Thrown from DeriveSessionKey when MbedTLS.hkdf returns a non-zero status, meaning HKDF (RFC 5869) key derivation failed inside the native mbedTLS library. HKDF is used to derive the per-session subkey from the salt and master key. A non-zero return almost always indicates an invalid parameter (bad lengths) rather than a random failure.","triggerScenarios":"saltLen, keyLen, or InfoBytes.Length passed to hkdf is zero or out of range; masterKey buffer shorter than keyLen; the salt buffer is null/undersized. These usually stem from a cipher whose EncryptorInfo declared wrong sizes, or from a salt that was not generated/padded correctly.","commonSituations":"A misconfigured AEAD cipher with incorrect KeySize/SaltSize in its EncryptorInfo; a custom method added without correct size metadata; buffer reuse bug leaving a salt shorter than declared.","solutions":["Verify the EncryptorInfo for the selected method declares correct KeySize, SaltSize, and InfoBytes.","Check that the salt buffer length equals saltLen and masterKey length is at least keyLen before calling.","If you added a custom AEAD method, confirm its sizes match the spec (e.g. GCM salt = 16, key = 16/32).","Log the exact lengths and the mbedTLS return code to pinpoint the bad parameter."],"exampleFix":"// before\nint ret = MbedTLS.hkdf(salt, saltLen, masterKey, keyLen, InfoBytes, InfoBytes.Length, sessionKey, keyLen);\nif (ret != 0) throw new System.Exception(\"failed to generate session key\");\n\n// after: include ret and lengths for diagnosis\nif (ret != 0)\n    throw new System.Exception($\"failed to generate session key (ret={ret}, saltLen={saltLen}, keyLen={keyLen})\");","handlingStrategy":"validation","validationCode":"// Validate buffer sizes before calling hkdf\nif (salt == null || salt.Length < saltLen) throw new ArgumentException(\"bad salt\");\nif (masterKey == null || masterKey.Length < keyLen) throw new ArgumentException(\"bad masterKey\");\nif (sessionKey == null || sessionKey.Length < keyLen) throw new ArgumentException(\"bad sessionKey\");","typeGuard":"bool SizesConsistent(EncryptorInfo i) =>\n    i.KeySize > 0 && i.SaltSize > 0 && i.NonceSize > 0 && i.TagSize > 0;","tryCatchPattern":"try { DeriveSessionKey(salt, masterKey, sessionKey); }\ncatch (Exception ex) when (ex.Message.Contains(\"session key\"))\n{ /* abort connection; log saltLen/keyLen/InfoBytes length */ }","preventionTips":["Keep EncryptorInfo size metadata correct per cipher spec.","Never pass a salt/key buffer shorter than its declared length.","Log the native return code to identify the bad HKDF parameter."],"tags":["encryption","aead","mbedtls","hkdf","key-derivation"],"backgroundTag":null,"analyzedSha":"891d971682eefcaa2e640258d3b352a3ad3b2233","analyzedAt":"2026-08-13T10:12:34.434Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}