peass-ng/PEASS-ng · error · ArgumentException
Tweak must be words.
Error message
Tweak must be words.
What it means
An argument validation in ThreefishEngine.SetTweak (invoked from Init): the tweak must be passed as exactly TWEAK_SIZE_WORDS (2) ulong words because the tweak schedule only accepts a two-word tweak; any other word count is rejected before the key schedule runs.
Source
Thrown at winPEAS/winPEASexe/winPEAS/3rdParty/BouncyCastle/crypto/engines/ThreefishEngine.cs:254
* Key and tweak word sequences are repeated, and static MOD17/MOD9/MOD5/MOD3 calculations
* used, to avoid expensive mod computations during cipher operation.
*/
ulong knw = C_240;
for (int i = 0; i < blocksizeWords; i++)
{
kw[i] = key[i];
knw = knw ^ kw[i];
}
kw[blocksizeWords] = knw;
Array.Copy(kw, 0, kw, blocksizeWords + 1, blocksizeWords);
}
private void SetTweak(ulong[] tweak)
{
if (tweak.Length != TWEAK_SIZE_WORDS)
{
throw new ArgumentException("Tweak must be " + TWEAK_SIZE_WORDS + " words.");
}
/*
* Tweak schedule partially repeated to avoid mod computations during cipher operation
*/
t[0] = tweak[0];
t[1] = tweak[1];
t[2] = t[0] ^ t[1];
t[3] = t[0];
t[4] = t[1];
}
public virtual string AlgorithmName
{
get { return "Threefish-" + (blocksizeBytes * 8); }
}
public virtual bool IsPartialBlockOkayView on GitHub (pinned to 53fb989abc)
Solutions
- Always pass a ulong[2] tweak (or null for no tweak)
- When converting 16 tweak bytes, build exactly two words: BytesToWord(tweak,0) and BytesToWord(tweak,8)
- Prefer the byte[]-based Init with ParametersWithTweak, which performs this conversion for you
Example fix
// before
ulong[] tweakWords = new ulong[] { t0 };
engine.Init(true, keyWords, tweakWords);
// after
ulong[] tweakWords = new ulong[] { t0, t1 };
engine.Init(true, keyWords, tweakWords); Defensive patterns
Strategy: validation
Validate before calling
if (tweakWords != null && tweakWords.Length != 2)
throw new ArgumentException("tweakWords must be exactly 2 ulong words");
engine.Init(forEncryption, keyWords, tweakWords); Type guard
bool IsValidTweakWords(ulong[] t) => t == null || t.Length == 2;
Try / catch
try { engine.Init(forEnc, keyWords, t); }
catch (ArgumentException) { /* pad/truncate to 2 words or pass null */ } Prevention
- Represent tweaks as ulong[2] in internal code
- Parse 16 tweak bytes into exactly two little-endian words
- Pass null rather than an empty/short array when there is no tweak
When it happens
Trigger: Calling the internal Init(forEncryption, keyWords, tweakWords) overload with a tweakWords array whose length is not 2 (e.g. 1-word tweak, 4-word tweak).
Common situations: Manual construction of tweak words; reusing tweak words loaded from a different format (e.g. 3-word wide tweak); off-by-one in parsing a 16-byte tweak into words.
Related errors
- Threefish tweak must be bytes
- Invalid blocksize - Threefish is defined with block size of
- Invalid parameter passed to Threefish init -
- Threefish key must be same size as block (
- Output buffer too short
AI-assisted analysis of peass-ng/PEASS-ng@53fb989abc (2026-09-02).
Data as JSON: /api/errors/34f85cc1936e9e33.
Report an issue: GitHub.