{"record":{"id":"6abdd64b32cca475","repo":"peass-ng/PEASS-ng","slug":"attempt-to-absorb-while-squeezing","errorCode":null,"errorMessage":"attempt to absorb while squeezing","messagePattern":"attempt to absorb while squeezing","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"winPEAS/winPEASexe/winPEAS/3rdParty/BouncyCastle/crypto/digests/KeccakDigest.cs","lineNumber":154,"sourceCode":"        private void InitSponge(int rate)\n        {\n            if (rate <= 0 || rate >= 1600 || (rate & 63) != 0)\n                throw new InvalidOperationException(\"invalid rate value\");\n\n            this.rate = rate;\n            Array.Clear(state, 0, state.Length);\n            Arrays.Fill(this.dataQueue, (byte)0);\n            this.bitsInQueue = 0;\n            this.squeezing = false;\n            this.fixedOutputLength = (1600 - rate) >> 1;\n        }\n\n        protected void Absorb(byte data)\n        {\n            if ((bitsInQueue & 7) != 0)\n                throw new InvalidOperationException(\"attempt to absorb with odd length queue\");\n            if (squeezing)\n                throw new InvalidOperationException(\"attempt to absorb while squeezing\");\n\n            dataQueue[bitsInQueue >> 3] = data;\n            if ((bitsInQueue += 8) == rate)\n            {\n                KeccakAbsorb(dataQueue, 0);\n                bitsInQueue = 0;\n            }\n        }\n\n        protected void Absorb(byte[] data, int off, int len)\n        {\n            if ((bitsInQueue & 7) != 0)\n                throw new InvalidOperationException(\"attempt to absorb with odd length queue\");\n            if (squeezing)\n                throw new InvalidOperationException(\"attempt to absorb while squeezing\");\n\n            int bytesInQueue = bitsInQueue >> 3;\n            int rateBytes = rate >> 3;","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/peass-ng/PEASS-ng/blob/53fb989abc2219826385683a6fee826bd6cd38d6/winPEAS/winPEASexe/winPEAS/3rdParty/BouncyCastle/crypto/digests/KeccakDigest.cs#L136-L172","documentation":"KeccakDigest.Absorb(byte) throws InvalidOperationException when the absorb phase is invoked after the squeeze phase has started (the `squeezing` flag is true). Keccak/SHA-3 is a two-phase sponge: all input must be absorbed before any output is squeezed; absorbing after switching to squeezing would corrupt the state. This single-byte overload is reached via Update().","triggerScenarios":"Calling digest.Update(...) (or BlockUpdate) after calling DoFinal has put the digest into squeezing phase — e.g. calling Update between two DoFinal calls without a Reset.","commonSituations":"Streaming hash of multiple parts where the developer reuses the digest instance after DoFinal without Reset; a helper that computes a final hash then appends more data; incremental hashing loops that over-run the final block.","solutions":["Call digest.Reset() before reusing the instance for a new hash computation.","Restructure code so all Update/BlockUpdate calls precede the single DoFinal call.","If a second hash over different data is needed, create a new KeccakDigest instance instead of reusing a finalized one."],"exampleFix":"// before\ndigest.BlockUpdate(part1, 0, part1.Length);\ndigest.DoFinal(hash1, 0);\ndigest.BlockUpdate(part2, 0, part2.Length); // throws\n// after\ndigest.BlockUpdate(part1, 0, part1.Length);\ndigest.DoFinal(hash1, 0);\ndigest.Reset();\ndigest.BlockUpdate(part2, 0, part2.Length);","handlingStrategy":"validation","validationCode":"// Track finalize state before each update\nbool finalized = false;\nvoid SafeUpdate(KeccakDigest d, byte b) {\n    if (finalized) throw new InvalidOperationException(\"Call Reset() before reusing the digest\");\n    d.Update(b);\n}","typeGuard":"bool IsUsable(KeccakDigest d, bool wasFinalized) => !wasFinalized;","tryCatchPattern":"try { digest.Update(data[i]); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"squeezing\")) { digest.Reset(); digest.Update(data[i]); }","preventionTips":["Treat IDigest instances as single-use: Reset() immediately after DoFinal().","Wrap digest usage in using/try-finally that resets the instance.","Never interleave Update and DoFinal across logical computations."],"tags":["csharp","bouncycastle","keccak","digest-state"],"backgroundTag":"digest-reuse-after-final","analyzedSha":"53fb989abc2219826385683a6fee826bd6cd38d6","analyzedAt":"2026-09-02T04:25:09.259Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T11:17:12.671Z"}