micro/go-micro · error

incoming message couldn't be verified / decrypted

Error message

incoming message couldn't be verified / decrypted

What it means

NaCl box authentication failed during Decrypt. naclbox.Open verifies the Poly1305 MAC using the derived shared key before decrypting; if verification fails, nothing is returned and this error is thrown. It means the ciphertext, nonce, sender public key, or recipient private key do not form the same key pair used for encryption.

Source

Thrown at config/secrets/box/box.go:85

	return naclbox.Seal(nonce[:], in, &nonce, &recipientPublicKey, &b.privateKey), nil
}

// Decrypt Decrypts a message with the receiver's private key and the sender's public key.
func (b *box) Decrypt(in []byte, opts ...secrets.DecryptOption) ([]byte, error) {
	var options secrets.DecryptOptions
	for _, o := range opts {
		o(&options)
	}
	if len(options.SenderPublicKey) != keyLength {
		return []byte{}, errors.New("sender's public key bust be provided")
	}
	var nonce [24]byte
	var senderPublicKey [32]byte
	copy(nonce[:], in[:24])
	copy(senderPublicKey[:], options.SenderPublicKey)
	decrypted, ok := naclbox.Open(nil, in[24:], &nonce, &senderPublicKey, &b.privateKey)
	if !ok {
		return []byte{}, errors.New("incoming message couldn't be verified / decrypted")
	}
	return decrypted, nil
}

View on GitHub (pinned to 24529f1404)

Solutions

  1. Verify the sender's public key and your private key are the exact complementary pair used at encryption time.
  2. Check that the ciphertext passed to Decrypt is untouched: first 24 bytes nonce, remainder ciphertext; do not trim, prepend, or base64-decode twice.
  3. Re-encrypt with the current keys and retry; if key rotation occurred, distribute the new sender public key to recipients.
  4. Add a checksum/version prefix at the application layer so mismatched keys are detected before naclbox.Open is attempted.

Example fix

// before
raw, _ := base64.StdEncoding.DecodeString(payload)
decrypted, err := b.Decrypt(raw, secrets.WithSenderPublicKey(wrongKey))
// after
raw, err := base64.StdEncoding.DecodeString(payload)
if err != nil { return err }
if len(raw) < 24 { return errors.New("ciphertext too short") }
decrypted, err := b.Decrypt(raw, secrets.WithSenderPublicKey(correctSenderPub))
Defensive patterns

Strategy: try-catch

Validate before calling

if len(ciphertext) <= 24 {
    return errors.New("ciphertext too short to contain nonce")
}

Try / catch

decrypted, err := b.Decrypt(data, secrets.WithSenderPublicKey(pub))
if err != nil {
    if strings.Contains(err.Error(), "couldn't be verified") {
        return fmt.Errorf("decryption failed: wrong keys or corrupted data: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling box.Decrypt on ciphertext that was not encrypted with the matching sender private key / recipient public key pair; corrupted or truncated ciphertext (in shorter than 24 bytes + ciphertext, or sliced incorrectly since the first 24 bytes are the nonce); supplying the wrong SenderPublicKey.

Common situations: Key rotation where one side still uses an old key; copy-pasting keys with whitespace or wrong encoding; accidentally re-slicing or mutating the encrypted payload before decryption; a sender encrypting with a different curve/key type than box expects.

Related errors


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/4e08606622d15bb2. Report an issue: GitHub.