peass-ng/PEASS-ng · error · InvalidOperationException
Threefish engine not initialised
Error message
Threefish engine not initialised
What it means
The internal ProcessBlock(ulong[], ulong[]) throws this InvalidOperationException when kw[blocksizeWords] == 0, i.e. the key-schedule extension word is still zero because Init() was never called (or was called with a null key, the documented way to mean 'not initialised'). Threefish requires a key and tweak to be set before any block can be processed; the parity/extension word doubles as the initialised flag.
Source
Thrown at winPEAS/winPEASexe/winPEAS/3rdParty/BouncyCastle/crypto/engines/ThreefishEngine.cs:323
WordToBytes(this.currentBlock[i >> 3], outBytes, outOff + i);
}
return blocksizeBytes;
}
/// <summary>
/// Process a block of data represented as 64 bit words.
/// </summary>
/// <returns>the number of 8 byte words processed (which will be the same as the block size).</returns>
/// <param name="inWords">a block sized buffer of words to process.</param>
/// <param name="outWords">a block sized buffer of words to receive the output of the operation.</param>
/// <exception cref="DataLengthException">if either the input or output is not block sized</exception>
/// <exception cref="InvalidOperationException">if this engine is not initialised</exception>
internal int ProcessBlock(ulong[] inWords, ulong[] outWords)
{
if (kw[blocksizeWords] == 0)
{
throw new InvalidOperationException("Threefish engine not initialised");
}
if (inWords.Length != blocksizeWords)
{
throw new DataLengthException("Input buffer too short");
}
if (outWords.Length != blocksizeWords)
{
throw new DataLengthException("Output buffer too short");
}
if (forEncryption)
{
cipher.EncryptBlock(inWords, outWords);
}
else
{
cipher.DecryptBlock(inWords, outWords);View on GitHub (pinned to 53fb989abc)
Solutions
- Call engine.Init(forEncryption, new TweakableBlockCipherParameters(key, tweak, null)) — or the appropriate IBlockCipherParameters — before the first ProcessBlock.
- Check initialization state in your wrapper: track a bool set in Init and throw/guard before processing if it's false.
- If you reset with a null key, re-Init with a real key before the next ProcessBlock.
- Never assume a newly constructed ThreefishEngine is usable: construction and initialisation are separate steps.
Example fix
// before var engine = new ThreefishEngine(256); engine.ProcessBlock(input, 0, output, 0); // InvalidOperationException: not initialised // after var engine = new ThreefishEngine(256); engine.Init(true, new TweakableBlockCipherParameters(new KeyParameter(key), tweak, null)); engine.ProcessBlock(input, 0, output, 0);
Defensive patterns
Strategy: validation
Validate before calling
// C#
if (!initialized)
throw new InvalidOperationException("Call Init(forEncryption, cipherParameters) before ProcessBlock");
engine.Init(forEncryption, new TweakableBlockCipherParameters(new KeyParameter(key), tweak, null)); Type guard
bool IsCipherReady(IBlockCipher engine, Func<bool> initTracker) => engine != null && initTracker();
Try / catch
try
{
engine.ProcessBlock(input, 0, output, 0);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("not initialised"))
{
throw new CryptographyException("Threefish engine used before Init() — supply key and tweak parameters first", ex);
} Prevention
- Treat construction and Init as one mandatory pair — never expose an un-initialised engine to callers.
- Track initialisation with a bool flag set inside your Init wrapper.
- Remember Init(forEncryption, null) de-initialises: re-Init with real parameters afterwards.
- Centralise cipher creation in a factory that always applies key parameters.
When it happens
Trigger: Calling ProcessBlock(ulong[] inWords, ulong[] outWords) (directly or via the byte[] overload) before calling Init(true/false, keyParameters), or after Init was passed a null key — ThreefishEngine treats Init(forEncryption, null) as 'de-initialise'.
Common situations: Reusing a freshly constructed engine without wiring key parameters; resetting the cipher with a null key and then continuing to process blocks; a code path that constructs the engine lazily but processes eagerly; mixing engines where only one of several got Init called.
Related errors
- Invalid blocksize - Threefish is defined with block size of
- Invalid parameter passed to Threefish init -
- Threefish key must be same size as block (
- Threefish tweak must be bytes
- Tweak must be words.
AI-assisted analysis of peass-ng/PEASS-ng@53fb989abc (2026-09-02).
Data as JSON: /api/errors/b41344e146e40934.
Report an issue: GitHub.