{"record":{"id":"34f85cc1936e9e33","repo":"peass-ng/PEASS-ng","slug":"tweak-must-be-words","errorCode":null,"errorMessage":"Tweak must be  words.","messagePattern":"Tweak must be  words\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"winPEAS/winPEASexe/winPEAS/3rdParty/BouncyCastle/crypto/engines/ThreefishEngine.cs","lineNumber":254,"sourceCode":"\t         * Key and tweak word sequences are repeated, and static MOD17/MOD9/MOD5/MOD3 calculations\n\t         * used, to avoid expensive mod computations during cipher operation.\n\t         */\n\n\t\t\tulong knw = C_240;\n\t\t\tfor (int i = 0; i < blocksizeWords; i++)\n\t\t\t{\n\t\t\t\tkw[i] = key[i];\n\t\t\t\tknw = knw ^ kw[i];\n\t\t\t}\n\t\t\tkw[blocksizeWords] = knw;\n\t\t\tArray.Copy(kw, 0, kw, blocksizeWords + 1, blocksizeWords);\n\t\t}\n\n\t\tprivate void SetTweak(ulong[] tweak)\n\t\t{\n\t\t\tif (tweak.Length != TWEAK_SIZE_WORDS)\n\t\t\t{\n\t\t\t\tthrow new ArgumentException(\"Tweak must be \" + TWEAK_SIZE_WORDS + \" words.\");\n\t\t\t}\n\n\t\t\t/*\n\t         * Tweak schedule partially repeated to avoid mod computations during cipher operation\n\t         */\n\t\t\tt[0] = tweak[0];\n\t\t\tt[1] = tweak[1];\n\t\t\tt[2] = t[0] ^ t[1];\n\t\t\tt[3] = t[0];\n\t\t\tt[4] = t[1];\n\t\t}\n\n\t\tpublic virtual string AlgorithmName\n\t\t{\n\t\t\tget { return \"Threefish-\" + (blocksizeBytes * 8); }\n\t\t}\n\n\t\tpublic virtual bool IsPartialBlockOkay","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/peass-ng/PEASS-ng/blob/53fb989abc2219826385683a6fee826bd6cd38d6/winPEAS/winPEASexe/winPEAS/3rdParty/BouncyCastle/crypto/engines/ThreefishEngine.cs#L236-L272","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nulong[] tweakWords = new ulong[] { t0 };\nengine.Init(true, keyWords, tweakWords);\n// after\nulong[] tweakWords = new ulong[] { t0, t1 };\nengine.Init(true, keyWords, tweakWords);","handlingStrategy":"validation","validationCode":"if (tweakWords != null && tweakWords.Length != 2)\n    throw new ArgumentException(\"tweakWords must be exactly 2 ulong words\");\nengine.Init(forEncryption, keyWords, tweakWords);","typeGuard":"bool IsValidTweakWords(ulong[] t) => t == null || t.Length == 2;","tryCatchPattern":"try { engine.Init(forEnc, keyWords, t); }\ncatch (ArgumentException) { /* pad/truncate to 2 words or pass null */ }","preventionTips":["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"],"tags":["csharp","cryptography","threefish","tweak"],"backgroundTag":"invalid-cipher-tweak-size","analyzedSha":"53fb989abc2219826385683a6fee826bd6cd38d6","analyzedAt":"2026-09-02T04:25:09.259Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T11:17:12.671Z"}