package security import ( "crypto/aes" "crypto/cipher" "encoding/base64" "errors" ) func DecryptAESGCM(b64 string, key []byte) (string, error) { if len(key) != 32 { return "", errors.New("encryption key must be 32 bytes for AES-256") } raw, err := base64.StdEncoding.DecodeString(b64) if err != nil { return "", err } block, err := aes.NewCipher(key) if err != nil { return "", err } // Probar con nonce de 12 y 16 bytes for _, ns := range []int{12, 16} { gcm, err := cipher.NewGCMWithNonceSize(block, ns) if err != nil { continue } // si no soporta ese ns, prueba el siguiente tagSize := gcm.Overhead() if len(raw) < ns+tagSize+1 { // al menos 1 byte de CT continue } nonce := raw[:ns] rest := raw[ns:] // A) nonce || ciphertext || tag (nativo Go) if pt, err := gcm.Open(nil, nonce, rest, nil); err == nil { return string(pt), nil } // B) nonce || tag || ciphertext (PyCryptodome ejemplo previo) if len(rest) > tagSize { tag := rest[:tagSize] ct := rest[tagSize:] repacked := append(ct, tag...) // => ciphertext||tag if pt, err := gcm.Open(nil, nonce, repacked, nil); err == nil { return string(pt), nil } } } return "", errors.New("GCM auth failed: wrong key, bad data, or unsupported layout") }