peass-ng/PEASS-ng · error · ArgumentException

Salt length must be exactly 8 bytes

Error message

Salt length must be exactly 8 bytes

What it means

Blake2s's parameter block reserves exactly 8 bytes for the salt field. The constructor copies the salt into a fixed 8-byte array, so it throws ArgumentException when salt != null but salt.Length != 8.

Source

Thrown at winPEAS/winPEASexe/winPEAS/3rdParty/BouncyCastle/crypto/digests/Blake2sDigest.cs:219

         *
         * @param key             a key up to 32 bytes or null
         * @param digestBytes     from 1 up to 32 bytes
         * @param salt            8 bytes or null
         * @param personalization 8 bytes or null
         */
        public Blake2sDigest(byte[] key, int digestBytes, byte[] salt,
                             byte[] personalization)
        {
            if (digestBytes < 1 || digestBytes > 32)
                throw new ArgumentException("Invalid digest length (required: 1 - 32)");

            this.digestLength = digestBytes;
            this.buffer = new byte[BLOCK_LENGTH_BYTES];

            if (salt != null)
            {
                if (salt.Length != 8)
                    throw new ArgumentException("Salt length must be exactly 8 bytes");

                this.salt = new byte[8];
                Array.Copy(salt, 0, this.salt, 0, salt.Length);
            }
            if (personalization != null)
            {
                if (personalization.Length != 8)
                    throw new ArgumentException("Personalization length must be exactly 8 bytes");

                this.personalization = new byte[8];
                Array.Copy(personalization, 0, this.personalization, 0, personalization.Length);
            }
            if (key != null)
            {
                if (key.Length > 32)
                    throw new ArgumentException("Keys > 32 bytes are not supported");

                this.key = new byte[key.Length];

View on GitHub (pinned to 53fb989abc)

Solutions

  1. Provide exactly 8 bytes of salt; truncate a longer value or right-pad a shorter one with zeros to 8 bytes.
  2. Pass null for salt if randomized salting is not required (the parameter block is then zero-filled).
  3. Validate the salt length before constructing the digest.

Example fix

// before
byte[] salt = new byte[16]; // 16-byte nonce
var digest = new Blake2sDigest(null, 32, salt, null);
// after
byte[] salt8 = new byte[8];
Array.Copy(salt, salt8, 8); // truncate to 8 bytes
var digest = new Blake2sDigest(null, 32, salt8, null);
Defensive patterns

Strategy: validation

Validate before calling

if (salt != null && salt.Length != 8)
    throw new ArgumentException("Blake2s salt must be exactly 8 bytes");
var digest = new Blake2sDigest(key, 32, salt, pers);

Type guard

static bool IsValidSalt(byte[] salt) => salt == null || salt.Length == 8;

Try / catch

try { var d = new Blake2sDigest(key, 32, salt, pers); }
catch (ArgumentException ex) { /* pad/truncate salt or pass null */ }

Prevention

When it happens

Trigger: Calling new Blake2sDigest(key, digestBytes, salt, personalization) with a non-null salt that is not exactly 8 bytes long (e.g. 16-byte random nonce, 4-byte seed, empty array, or Base64-decoded salt of another size).

Common situations: Using a standard 16-byte AES IV or random nonce as the Blake2 salt; forgetting the algorithm-specific 8-byte requirement when porting from another hash; truncating/zero-padding salts incorrectly.

Related errors


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