{"record":{"id":"970f84219497e44a","repo":"shadowsocks/shadowsocks-windows","slug":"openssl-cannot-set-key","errorCode":null,"errorMessage":"openssl: cannot set key","messagePattern":"openssl: cannot set key","errorType":"exception","errorClass":"System.Exception","httpStatus":null,"severity":"critical","filePath":"shadowsocks-csharp/Encryption/AEAD/AEADOpenSSLEncryptor.cs","lineNumber":81,"sourceCode":"            DeriveSessionKey(isEncrypt ? _encryptSalt : _decryptSalt, _Masterkey,\r\n                isEncrypt ? _opensslEncSubkey : _opensslDecSubkey);\r\n\r\n            var ret = OpenSSL.EVP_CipherInit_ex(ctx, _cipherInfoPtr, IntPtr.Zero, null, null,\r\n                isEncrypt ? OpenSSL.OPENSSL_ENCRYPT : OpenSSL.OPENSSL_DECRYPT);\r\n            if (ret != 1) throw new System.Exception(\"openssl: fail to init ctx\");\r\n\r\n            ret = OpenSSL.EVP_CIPHER_CTX_set_key_length(ctx, keyLen);\r\n            if (ret != 1) throw new System.Exception(\"openssl: fail to set key length\");\r\n\r\n            ret = OpenSSL.EVP_CIPHER_CTX_ctrl(ctx, OpenSSL.EVP_CTRL_AEAD_SET_IVLEN,\r\n                nonceLen, IntPtr.Zero);\r\n            if (ret != 1) throw new System.Exception(\"openssl: fail to set AEAD nonce length\");\r\n\r\n            ret = OpenSSL.EVP_CipherInit_ex(ctx, IntPtr.Zero, IntPtr.Zero,\r\n                isEncrypt ? _opensslEncSubkey : _opensslDecSubkey,\r\n                null,\r\n                isEncrypt ? OpenSSL.OPENSSL_ENCRYPT : OpenSSL.OPENSSL_DECRYPT);\r\n            if (ret != 1) throw new System.Exception(\"openssl: cannot set key\");\r\n            OpenSSL.EVP_CIPHER_CTX_set_padding(ctx, 0);\r\n        }\r\n\r\n        public override void cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen)\r\n        {\r\n            OpenSSL.SetCtxNonce(_encryptCtx, _encNonce, true);\r\n            // buf: all plaintext\r\n            // outbuf: ciphertext + tag\r\n            int ret;\r\n            int tmpLen = 0;\r\n            clen = 0;\r\n            var tagBuf = new byte[tagLen];\r\n\r\n            ret = OpenSSL.EVP_CipherUpdate(_encryptCtx, ciphertext, out tmpLen,\r\n                plaintext, (int) plen);\r\n            if (ret != 1) throw new CryptoErrorException(\"openssl: fail to encrypt AEAD\");\r\n            clen += (uint) tmpLen;\r\n            // For AEAD cipher, it should not output anything\r","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/shadowsocks/shadowsocks-windows/blob/891d971682eefcaa2e640258d3b352a3ad3b2233/shadowsocks-csharp/Encryption/AEAD/AEADOpenSSLEncryptor.cs#L63-L99","documentation":"Thrown from AEADOpenSSLEncryptor.InitCipher on the second EVP_CipherInit_ex (the call that supplies the actual subkey) returning != 1. By this point the cipher, IV length, and key length are set; supplying the key finalises the context. Failure indicates the key itself was rejected (wrong length vs the set key length) or the context is inconsistent.","triggerScenarios":"The subkey buffer (_opensslEncSubkey/_opensslDecSubkey) length differs from the key length set in the prior step; DeriveSessionKey produced fewer bytes than keyLen; the context was mutated between the two init calls.","commonSituations":"A session-key derivation bug yielding a short key; reusing a context that was partially initialised; thread races writing the subkey buffer.","solutions":["Verify the subkey buffer passed is exactly keyLen bytes and was fully written by DeriveSessionKey.","Ensure no code path mutates the context between the two EVP_CipherInit_ex calls.","Log keyLen vs actual buffer length to catch derivation shortfalls."],"exampleFix":"// before\nret = OpenSSL.EVP_CipherInit_ex(ctx, IntPtr.Zero, IntPtr.Zero, isEncrypt ? _opensslEncSubkey : _opensslDecSubkey, null, isEncrypt ? OpenSSL.OPENSSL_ENCRYPT : OpenSSL.OPENSSL_DECRYPT);\nif (ret != 1) throw new System.Exception(\"openssl: cannot set key\");\n\n// after\nvar keyBuf = isEncrypt ? _opensslEncSubkey : _opensslDecSubkey;\nif (ret != 1)\n    throw new System.Exception($\"openssl: cannot set key (ret={ret}, bufLen={keyBuf.Length}, expected={keyLen})\");","handlingStrategy":"validation","validationCode":"// Verify the subkey buffer length matches keyLen before the second init\nbyte[] keyBuf = isEncrypt ? _opensslEncSubkey : _opensslDecSubkey;\nif (keyBuf == null || keyBuf.Length != keyLen)\n    throw new ArgumentException($\"subkey length {keyBuf?.Length ?? -1} != keyLen {keyLen}\");","typeGuard":"bool SubKeyLengthOk(byte[] buf, int keyLen) =>\n    buf != null && buf.Length == keyLen;","tryCatchPattern":"try { OpenSSL.EVP_CipherInit_ex(ctx, IntPtr.Zero, IntPtr.Zero, keyBuf, null, enc); }\ncatch (Exception ex) when (ex.Message.Contains(\"cannot set key\"))\n{ /* re-derive session key, recreate ctx, retry once */ }","preventionTips":["Ensure DeriveSessionKey writes exactly keyLen bytes into the subkey buffer.","Do not mutate the context between the two EVP_CipherInit_ex calls.","Log buffer length vs keyLen on failure to catch derivation bugs."],"tags":["encryption","aead","openssl","key","initialization"],"backgroundTag":null,"analyzedSha":"891d971682eefcaa2e640258d3b352a3ad3b2233","analyzedAt":"2026-08-13T10:12:34.434Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}