golang/go · error

cipher: NewGCM requires 128-bit block cipher

Error message

cipher: NewGCM requires 128-bit block cipher

What it means

GCM (Galois/Counter Mode) is mathematically defined only for block ciphers with a 128-bit (16-byte) block. This fallback code path runs when the cipher does not implement the gcmAble interface (i.e. no hardware/assembly acceleration) and its BlockSize() is not gcmBlockSize (16). AES in all key sizes has 128-bit blocks, so it passes; ciphers like Blowfish (64-bit) do not.

Source

Thrown at src/crypto/cipher/gcm.go:214

// gcmAble is an interface implemented by ciphers that have a specific optimized
// implementation of GCM. crypto/aes doesn't use this anymore, and we'd like to
// eventually remove it.
type gcmAble interface {
	NewGCM(nonceSize, tagSize int) (AEAD, error)
}

func newGCMFallback(cipher Block, nonceSize, tagSize int) (AEAD, error) {
	if tagSize < gcmMinimumTagSize || tagSize > gcmBlockSize {
		return nil, errors.New("cipher: incorrect tag size given to GCM")
	}
	if nonceSize <= 0 {
		return nil, errors.New("cipher: the nonce can't have zero length")
	}
	if cipher, ok := cipher.(gcmAble); ok {
		return cipher.NewGCM(nonceSize, tagSize)
	}
	if cipher.BlockSize() != gcmBlockSize {
		return nil, errors.New("cipher: NewGCM requires 128-bit block cipher")
	}
	return &gcmFallback{cipher: cipher, nonceSize: nonceSize, tagSize: tagSize}, nil
}

// gcmFallback is only used for non-AES ciphers, which regrettably we
// theoretically support. It's a copy of the generic implementation from
// crypto/internal/fips140/aes/gcm/gcm_generic.go, refer to that file for more details.
type gcmFallback struct {
	cipher    Block
	nonceSize int
	tagSize   int
}

func (g *gcmFallback) NonceSize() int {
	return g.nonceSize
}

func (g *gcmFallback) Overhead() int {

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Use an AES block cipher: block, err := aes.NewCipher(key) then cipher.NewGCM(block).
  2. If you must use a 64-bit block cipher, choose a different AEAD construction (e.g. CTR mode + HMAC) instead of GCM.
  3. Guard before calling NewGCM: verify block.BlockSize() == 16 and surface a clear error otherwise.

Example fix

// before
block, _ := blowfish.NewCipher(key)
gcm, _ := cipher.NewGCM(block)
// after
block, _ := aes.NewCipher(key) // AES has a 128-bit block
gcm, _ := cipher.NewGCM(block)
Defensive patterns

Strategy: validation

Validate before calling

// Guard before NewGCM for any non-AES or custom cipher:
func newGCM(block cipher.Block) (cipher.AEAD, error) {
    if block.BlockSize() != 16 {
        return nil, fmt.Errorf("GCM needs a 128-bit block cipher, got %d-byte blocks", block.BlockSize())
    }
    return cipher.NewGCM(block)
}

Type guard

func isAESBlockSize(b cipher.Block) bool { return b.BlockSize() == 16 }

Prevention

When it happens

Trigger: Calling cipher.NewGCM(block) (which routes to newGCMFallback when the cipher is not gcmAble) with a Block whose BlockSize() != 16. Concretely: wrapping a blowfish.NewCipher block, a Twofish-style 128-bit block that lacks gcmAble implementation details aside, or any custom cipher.Block returning a non-16 BlockSize.

Common situations: Selecting GCM as the AEAD over a legacy or non-AES block cipher; writing a custom Block implementation; migrating code that paired GCM with an unexpected cipher; assuming GCM works with any cipher.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/4412ef5d8c2131ff. Report an issue: GitHub.