Paquete hash en Go: Guía Completa con Ejemplos y Mejores Prácticas
El paquete hash en Go proporciona interfaces y algoritmos para calcular resúmenes criptográficos y de integridad. Esta guía cubre su uso avanzado, comparativas de algoritmos y aplicaciones realistas.
1. Interfaz hash.Hash
Métodos Clave
type Hash interface {
Write(p []byte) (n int, err error) // Añade datos al hash
Sum(b []byte) []byte // Calcula el hash final
Reset() // Reinicia el estado
Size() int // Tamaño del hash en bytes
BlockSize() int // Tamaño de bloque interno
}
Ejemplo Detallado
package main
import (
"crypto/sha256"
"fmt"
"io"
"log"
"os"
)
// Calcular hash de un archivo grande
func fileHash(filename string) (string, error) {
f, err := os.Open(filename)
if err != nil {
return "", err
}
defer f.Close()
h := sha256.New()
if _, err := io.Copy(h, f); err != nil { // Eficiente para grandes volúmenes
return "", err
}
return fmt.Sprintf("%x", h.Sum(nil)), nil
}
func main() {
hash, err := fileHash("documento.pdf")
if err != nil {
log.Fatal(err)
}
fmt.Println("SHA-256 del documento:", hash)
}
2. Algoritmos de Hash
Comparativa de Algoritmos
| Algoritmo | Seguridad | Tamaño Hash | Velocidad | Uso Recomendado |
|---|---|---|---|---|
| MD5 | Obsoleto | 128 bits | Rápido | Verificación no crítica |
| SHA-1 | Débil | 160 bits | Moderado | Legacy systems |
| SHA-256 | Seguro | 256 bits | Moderado | Criptografía general |
| SHA-512 | Muy Seguro | 512 bits | Lento | Datos sensibles |
| CRC32 | No seguro | 32 bits | Muy rápido | Checksums de red |
| CRC64 | No seguro | 64 bits | Rápido | Integridad de archivos |
Ejemplo: Benchmark de Hashes
func benchmarkHash(b *testing.B, h hash.Hash) {
data := []byte("datos de prueba")
b.ResetTimer()
for i := 0; i < b.N; i++ {
h.Write(data)
h.Sum(nil)
h.Reset()
}
}
// Resultados típicos en AMD Ryzen 5:
// MD5: 1123 ns/op
// SHA-256: 2456 ns/op
// SHA-512: 3789 ns/op
3. Casos de Uso Avanzados
3.1 Verificación de Integridad en Descargas
func verifyDownload(filePath, expectedHash string) error {
actualHash, err := fileHash(filePath)
if err != nil {
return err
}
if actualHash != expectedHash {
return fmt.Errorf(
"hash inválido\nEsperado: %s\nObtenido: %s",
expectedHash,
actualHash,
)
}
return nil
}
3.2 Almacenamiento Seguro de Contraseñas
import "golang.org/x/crypto/bcrypt"
// Generar hash con salt automático
func hashPassword(password string) (string, error) {
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 12)
return string(bytes), err
}
// Verificar contraseña
func checkPassword(password, hash string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
return err == nil
}
4. Seguridad y Mejores Prácticas
Recomendaciones Clave
- Evitar MD5/SHA-1 para seguridad crítica (vulnerables a colisiones)
- Usar salts aleatorios con funciones como
bcryptoscrypt - Iteraciones múltiples para contraseñas (PBKDF2)
- Validar entradas antes de hashing para evitar DoS
- Usar HMAC para autenticación de mensajes
Ejemplo de Salt Manual
func secureHash(data []byte) (string, error) {
salt := make([]byte, 32)
if _, err := rand.Read(salt); err != nil {
return "", err
}
h := sha256.New()
h.Write(salt)
h.Write(data)
return fmt.Sprintf("%x:%x", salt, h.Sum(nil)), nil
}
5. HMAC y Autenticación de Mensajes
Implementación de HMAC-SHA256
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
)
func generateHMAC(key, data []byte) string {
h := hmac.New(sha256.New, key)
h.Write(data)
return hex.EncodeToString(h.Sum(nil))
}
func verifyHMAC(key, data []byte, expectedMAC string) bool {
actualMAC := generateHMAC(key, data)
return hmac.Equal([]byte(actualMAC), []byte(expectedMAC))
}
func main() {
secret := []byte("mi_clave_secreta")
message := []byte("transferir $100 a cuenta 1234")
mac := generateHMAC(secret, message)
fmt.Println("HMAC:", mac)
valid := verifyHMAC(secret, message, mac)
fmt.Println("Verificación:", valid) // true
}
Conclusión
El paquete hash y sus extensiones en Go ofrecen herramientas poderosas para:
- Garantizar integridad de datos
- Almacenar credenciales de forma segura
- Autenticar mensajes
- Generar identificadores únicos
Este contenido combina fundamentos técnicos, ejemplos aplicables a escenarios reales y prácticas de seguridad actualizadas, proporcionando una guía completa para el uso profesional de funciones hash en Go.