JuliusBrussee/caveman · error

envelope: gcm

Error message

envelope: gcm: %w

What it means

seal constructs an AES-GCM instance with cipher.NewGCM(block) and wraps failure as 'envelope: gcm: %w'. NewGCM only fails if the underlying cipher's block size is nonstandard, so with the library's own AES block this is effectively an internal invariant failure.

Solutions

  1. Inspect the wrapped cause; confirm crypto/aes is the standard implementation (BlockSize 16).
  2. Remove any custom crypto replacements/overrides in the build.
  3. Rebuild with the official Go toolchain and redeploy.
  4. File a bug with the wrapped error if it persists on a standard build.
Defensive patterns

Strategy: try-catch

Try / catch

ciphertext, meta, err := envelope.Seal(plaintext, aad)
if err != nil {
    if strings.Contains(err.Error(), "envelope: gcm") {
        log.Fatalf("GCM construction failed — crypto stack invariant broken: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: Seal/SealForScope calling cipher.NewGCM on a block cipher whose BlockSize() != 16 — not reachable with the standard aes.NewCipher output unless the crypto stack is replaced.

Common situations: Patched or vendor-replaced crypto packages; exotic Go toolchains; test doubles injected in place of crypto/aes.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/04efe27d8db669b7. Report an issue: GitHub.

Appendix: source

Thrown at shared/platform/envelope/envelope.go:80

	aad, scopeHash, err := scopeAAD(scope)
	if err != nil {
		return nil, nil, err
	}
	return seal(plaintext, schemeV2, aad, scopeHash)
}

func seal(plaintext []byte, scheme string, aad []byte, scopeHash string) (ciphertext []byte, metaJSON []byte, err error) {
	dataKey := make([]byte, 32)
	if _, err := rand.Read(dataKey); err != nil {
		return nil, nil, fmt.Errorf("envelope: data key entropy: %w", err)
	}
	block, err := aes.NewCipher(dataKey)
	if err != nil {
		return nil, nil, fmt.Errorf("envelope: aes: %w", err)
	}
	gcm, err := cipher.NewGCM(block)
	if err != nil {
		return nil, nil, fmt.Errorf("envelope: gcm: %w", err)
	}
	nonce := make([]byte, gcm.NonceSize())
	if _, err := rand.Read(nonce); err != nil {
		return nil, nil, fmt.Errorf("envelope: nonce entropy: %w", err)
	}
	ciphertext = gcm.Seal(nonce, nonce, plaintext, aad)

	wrapped, err := secretbox.EncryptPayloadKey(dataKey)
	if err != nil {
		return nil, nil, fmt.Errorf("envelope: wrap data key: %w", err)
	}
	meta := Metadata{Scheme: scheme, WrappedDataKey: base64.StdEncoding.EncodeToString(wrapped), ScopeHash: scopeHash}
	metaJSON, err = json.Marshal(meta)
	if err != nil {
		return nil, nil, fmt.Errorf("envelope: marshal metadata: %w", err)
	}
	return ciphertext, metaJSON, nil
}

View on GitHub (pinned to 3ee70a1026)