peass-ng/PEASS-ng · error · ArgumentException

must be in the range [0,7]

Error message

must be in the range [0,7]

What it means

Sha3Digest.DoFinal's partial-byte overload throws ArgumentException when `partialBits` is negative or greater than 7. It represents how many low bits of `partialByte` are valid input; SHA-3 additionally appends a 2-bit domain suffix, so any out-of-range count would corrupt the padding. Unlike KeccakDigest.AbsorbBits, 0 partial bits is allowed here.

Source

Thrown at winPEAS/winPEASexe/winPEAS/3rdParty/BouncyCastle/crypto/digests/SHA3Digest.cs:63

        public override string AlgorithmName
        {
            get { return "SHA3-" + fixedOutputLength; }
        }

        public override int DoFinal(byte[] output, int outOff)
        {
            AbsorbBits(0x02, 2);

            return base.DoFinal(output,  outOff);
        }

        /*
         * TODO Possible API change to support partial-byte suffixes.
         */
        protected override int DoFinal(byte[] output, int outOff, byte partialByte, int partialBits)
        {
            if (partialBits < 0 || partialBits > 7)
                throw new ArgumentException("must be in the range [0,7]", "partialBits");

            int finalInput = (partialByte & ((1 << partialBits) - 1)) | (0x02 << partialBits);
            Debug.Assert(finalInput >= 0);
            int finalBits = partialBits + 2;

            if (finalBits >= 8)
            {
                Absorb((byte)finalInput);
                finalBits -= 8;
                finalInput >>= 8;
            }

            return base.DoFinal(output, outOff, (byte)finalInput, finalBits);
        }

        public override IMemoable Copy()
		{
			return new Sha3Digest(this);

View on GitHub (pinned to 53fb989abc)

Solutions

  1. Validate that partialBits is in [0,7] before calling DoFinal; mask with & 7 only after validating.
  2. If more than 7 bits remain, absorb them via BlockUpdate as whole bytes first.
  3. Check signedness of the bit-count arithmetic in the caller (negative underflow).

Example fix

// before
int partialBits = remainingBits; // could be > 7 or negative on underflow
digest.DoFinal(output, outOff, partialByte, partialBits);
// after
if (partialBits < 0 || partialBits > 7)
    throw new ArgumentOutOfRangeException(nameof(partialBits));
digest.BlockUpdate(bytes, 0, bytes.Length); // whole bytes first
digest.DoFinal(output, outOff, partialByte, partialBits);
Defensive patterns

Strategy: validation

Validate before calling

if (partialBits < 0 || partialBits > 7)
    throw new ArgumentOutOfRangeException(nameof(partialBits), "must be in the range [0,7]");
digest.DoFinal(output, outOff, partialByte, partialBits);

Type guard

bool IsValidSha3PartialBits(int bits) => (uint)bits <= 7u; // also rejects negatives

Try / catch

try { digest.DoFinal(outBuf, 0, partialByte, partialBits); } catch (ArgumentException ex) when (ex.ParamName == "partialBits") { partialBits &= 7; digest.Reset(); /* replay with corrected value */ }

Prevention

When it happens

Trigger: Passing partialBits < 0 or > 7 to DoFinal(output, outOff, partialByte, partialBits), typically from an upstream bit-count computation bug.

Common situations: Implementing KMAC/TupleHash-style suffixes where the partial-bit counter overflows or is negative due to unsigned/signed confusion; ported code passing byte counts instead of bit counts.

Related errors


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