shadowsocks/shadowsocks-windows · critical · System.Exception
openssl: fail to create ctx
Error message
openssl: fail to create ctx
What it means
Thrown from AEADOpenSSLEncryptor.InitCipher when OpenSSL.EVP_CIPHER_CTX_new returns IntPtr.Zero, meaning OpenSSL could not allocate a new cipher context. Allocation failure is almost always a sign of an uninitialized or broken OpenSSL library (the context struct is tiny, so genuine out-of-memory is rare).
Source
Thrown at shadowsocks-csharp/Encryption/AEAD/AEADOpenSSLEncryptor.cs:52
};
public static List<string> SupportedCiphers()
{
return new List<string>(_ciphers.Keys);
}
protected override Dictionary<string, EncryptorInfo> getCiphers()
{
return _ciphers;
}
public override void InitCipher(byte[] salt, bool isEncrypt, bool isUdp)
{
base.InitCipher(salt, isEncrypt, isUdp);
_cipherInfoPtr = OpenSSL.GetCipherInfo(_innerLibName);
if (_cipherInfoPtr == IntPtr.Zero) throw new System.Exception("openssl: cipher not found");
IntPtr ctx = OpenSSL.EVP_CIPHER_CTX_new();
if (ctx == IntPtr.Zero) throw new System.Exception("openssl: fail to create ctx");
if (isEncrypt)
{
_encryptCtx = ctx;
}
else
{
_decryptCtx = ctx;
}
DeriveSessionKey(isEncrypt ? _encryptSalt : _decryptSalt, _Masterkey,
isEncrypt ? _opensslEncSubkey : _opensslDecSubkey);
var ret = OpenSSL.EVP_CipherInit_ex(ctx, _cipherInfoPtr, IntPtr.Zero, null, null,
isEncrypt ? OpenSSL.OPENSSL_ENCRYPT : OpenSSL.OPENSSL_DECRYPT);
if (ret != 1) throw new System.Exception("openssl: fail to init ctx");
ret = OpenSSL.EVP_CIPHER_CTX_set_key_length(ctx, keyLen);
View on GitHub (pinned to 891d971682)
Solutions
- Ensure OpenSSL is initialised before any crypto call (modern OpenSSL auto-inits, but check for explicit cleanup elsewhere).
- Confirm the correct libcrypto is loaded (no DLL hijack / wrong bitness).
- Avoid calling crypto during process shutdown / after global cleanup.
- If it persists, switch to the mbedTLS backend.
Example fix
// before
IntPtr ctx = OpenSSL.EVP_CIPHER_CTX_new();
if (ctx == IntPtr.Zero) throw new System.Exception("openssl: fail to create ctx");
// after
IntPtr ctx = OpenSSL.EVP_CIPHER_CTX_new();
if (ctx == IntPtr.Zero)
throw new System.Exception("openssl: fail to create ctx (library not initialised or wrong libcrypto loaded)"); Defensive patterns
Strategy: fallback
Validate before calling
// Ensure OpenSSL is usable before relying on it IntPtr probe = OpenSSL.EVP_CIPHER_CTX_new(); if (probe == IntPtr.Zero) /* fall back to mbedTLS */ else OpenSSL.EVP_CIPHER_CTX_free(probe);
Type guard
bool OpenSSLReady() => OpenSSL.EVP_CIPHER_CTX_new() != IntPtr.Zero;
Try / catch
try { useOpenSSL(); }
catch (Exception ex) when (ex.Message.Contains("fail to create ctx"))
{ /* fall back to mbedTLS backend; likely OpenSSL not initialised/wrong lib */ } Prevention
- Load the correct libcrypto (matching bitness and version).
- Avoid calling crypto during process teardown.
- Prefer the mbedTLS backend if OpenSSL init is unreliable in your host.
When it happens
Trigger: OpenSSL was not initialised (no OPENSSL_init_crypto / legacy init) before EVP_CIPHER_CTX_new; the native library failed to load or was already torn down; calling into OpenSSL after it was globally cleaned up.
Common situations: Mixing OpenSSL versions across native deps; calling crypto after EVP_cleanup/atexit; a DLL hijack loading the wrong libcrypto; process shutdown racing with crypto teardown.
Related errors
- openssl: cipher not found
- Cannot initialize mbed TLS cipher context
- failed to finish preparation
- openssl: fail to init ctx
- openssl: fail to set key length
AI-assisted analysis of shadowsocks/shadowsocks-windows@891d971682 (2026-08-13).
Data as JSON: /api/errors/adcee774cdec0546.
Report an issue: GitHub.