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 IsPartialBlockOkay

View on GitHub (pinned to 53fb989abc)

Solutions

  1. Always pass a ulong[2] tweak (or null for no tweak)
  2. When converting 16 tweak bytes, build exactly two words: BytesToWord(tweak,0) and BytesToWord(tweak,8)
  3. 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

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


AI-assisted analysis of peass-ng/PEASS-ng@53fb989abc (2026-09-02). Data as JSON: /api/errors/34f85cc1936e9e33. Report an issue: GitHub.