2025-10-15 10:43:58 -04:00

54 lines
1.3 KiB
Go

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")
}