feat: 16 funciones cybersecurity — análisis, crypto e IO de seguridad

12 funciones puras con implementación real:
HashSHA256, HashMD5, EntropyShannon, IsBase64, IsHex, ExtractURLs,
ParseIPCIDR, IPInRange, NormalizeURL, DetectSQLInjection,
LevenshteinDistance, JaccardSimilarity

4 funciones impuras con implementación real (stdlib):
LookupWhois, ResolveDNS, FetchHTTPHeaders, ScanPortTCP

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-28 02:23:41 +01:00
parent fc734029c1
commit bd9383fd82
32 changed files with 759 additions and 0 deletions
@@ -0,0 +1,33 @@
package cybersecurity
import (
"regexp"
"strings"
)
var sqliPatterns = []struct {
name string
re *regexp.Regexp
}{
{"union_select", regexp.MustCompile(`(?i)\bunion\s+(all\s+)?select\b`)},
{"or_1_eq_1", regexp.MustCompile(`(?i)\bor\s+1\s*=\s*1`)},
{"comment_injection", regexp.MustCompile(`(--|#|/\*)\s*$`)},
{"single_quote_or", regexp.MustCompile(`(?i)'\s*(or|and)\s+'`)},
{"drop_table", regexp.MustCompile(`(?i)\bdrop\s+(table|database)\b`)},
{"sleep_benchmark", regexp.MustCompile(`(?i)\b(sleep|benchmark)\s*\(`)},
{"exec_xp", regexp.MustCompile(`(?i)\b(exec|xp_)\w*`)},
{"tautology", regexp.MustCompile(`(?i)\bor\s+['"]?\w+['"]?\s*=\s*['"]?\w+['"]?`)},
{"stacked_query", regexp.MustCompile(`;\s*(select|insert|update|delete|drop|alter)\b`)},
}
// DetectSQLInjection analiza un input en busca de patrones heuristicos de inyeccion SQL.
// Devuelve si se detecto una amenaza y el nombre del patron encontrado.
func DetectSQLInjection(input string) (isThreat bool, pattern string) {
normalized := strings.TrimSpace(input)
for _, p := range sqliPatterns {
if p.re.MatchString(normalized) {
return true, p.name
}
}
return false, ""
}
@@ -0,0 +1,21 @@
---
name: detect_sql_injection
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func DetectSQLInjection(input string) (isThreat bool, pattern string)"
description: "Analiza un input en busca de patrones heuristicos de inyeccion SQL y devuelve si se detecto amenaza y el patron encontrado."
tags: [cybersecurity, sqli, detection, security]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [regexp, strings]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/detect_sql_injection.go"
---
@@ -0,0 +1,26 @@
package cybersecurity
import "math"
// EntropyShannon calcula la entropia de Shannon de los datos proporcionados.
// Devuelve un valor entre 0 (datos uniformes) y 8 (datos completamente aleatorios para bytes).
func EntropyShannon(data []byte) float64 {
if len(data) == 0 {
return 0
}
var freq [256]float64
for _, b := range data {
freq[b]++
}
n := float64(len(data))
entropy := 0.0
for _, f := range freq {
if f > 0 {
p := f / n
entropy -= p * math.Log2(p)
}
}
return entropy
}
@@ -0,0 +1,21 @@
---
name: entropy_shannon
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func EntropyShannon(data []byte) float64"
description: "Calcula la entropia de Shannon de un slice de bytes. Retorna un valor entre 0 y 8 bits por byte."
tags: [cybersecurity, entropy, shannon, analysis]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [math]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/entropy_shannon.go"
---
+14
View File
@@ -0,0 +1,14 @@
package cybersecurity
import "regexp"
var urlRegex = regexp.MustCompile(`https?://[^\s<>"'` + "`" + `\)\]\}]+`)
// ExtractURLs extrae todas las URLs (http/https) encontradas en el texto proporcionado.
func ExtractURLs(text string) []string {
matches := urlRegex.FindAllString(text, -1)
if matches == nil {
return []string{}
}
return matches
}
+21
View File
@@ -0,0 +1,21 @@
---
name: extract_urls
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func ExtractURLs(text string) []string"
description: "Extrae todas las URLs HTTP/HTTPS de un texto usando expresiones regulares."
tags: [cybersecurity, extract, url, parse]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [regexp]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/extract_urls.go"
---
@@ -0,0 +1,27 @@
package cybersecurity
import (
"fmt"
"net/http"
"time"
)
// FetchHTTPHeaders realiza una solicitud HTTP HEAD a la URL y devuelve los headers de respuesta.
func FetchHTTPHeaders(url string) (map[string][]string, error) {
client := &http.Client{
Timeout: 10 * time.Second,
}
resp, err := client.Head(url)
if err != nil {
return nil, fmt.Errorf("error realizando solicitud HEAD a %s: %w", url, err)
}
defer resp.Body.Close()
headers := make(map[string][]string, len(resp.Header))
for k, v := range resp.Header {
headers[k] = v
}
return headers, nil
}
@@ -0,0 +1,21 @@
---
name: fetch_http_headers
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: impure
signature: "func FetchHTTPHeaders(url string) (map[string][]string, error)"
description: "Realiza una solicitud HTTP HEAD a una URL y devuelve los headers de la respuesta."
tags: [cybersecurity, io, http, headers]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [fmt, net/http, time]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/fetch_http_headers.go"
---
+12
View File
@@ -0,0 +1,12 @@
package cybersecurity
import (
"crypto/md5"
"encoding/hex"
)
// HashMD5 calcula el hash MD5 de los datos proporcionados y devuelve el resultado como string hexadecimal.
func HashMD5(data []byte) string {
h := md5.Sum(data)
return hex.EncodeToString(h[:])
}
+21
View File
@@ -0,0 +1,21 @@
---
name: hash_md5
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func HashMD5(data []byte) string"
description: "Calcula el hash MD5 de un slice de bytes y devuelve el resultado como string hexadecimal."
tags: [cybersecurity, hash, md5, crypto]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [crypto/md5, encoding/hex]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/hash_md5.go"
---
+12
View File
@@ -0,0 +1,12 @@
package cybersecurity
import (
"crypto/sha256"
"encoding/hex"
)
// HashSHA256 calcula el hash SHA-256 de los datos proporcionados y devuelve el resultado como string hexadecimal.
func HashSHA256(data []byte) string {
h := sha256.Sum256(data)
return hex.EncodeToString(h[:])
}
+21
View File
@@ -0,0 +1,21 @@
---
name: hash_sha256
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func HashSHA256(data []byte) string"
description: "Calcula el hash SHA-256 de un slice de bytes y devuelve el resultado como string hexadecimal."
tags: [cybersecurity, hash, sha256, crypto]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [crypto/sha256, encoding/hex]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/hash_sha256.go"
---
+16
View File
@@ -0,0 +1,16 @@
package cybersecurity
import "net"
// IPInRange verifica si una direccion IP esta dentro de un rango CIDR dado.
func IPInRange(ip, cidr string) bool {
parsedIP := net.ParseIP(ip)
if parsedIP == nil {
return false
}
_, ipNet, err := net.ParseCIDR(cidr)
if err != nil {
return false
}
return ipNet.Contains(parsedIP)
}
+21
View File
@@ -0,0 +1,21 @@
---
name: ip_in_range
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func IPInRange(ip, cidr string) bool"
description: "Verifica si una direccion IP se encuentra dentro de un rango CIDR dado."
tags: [cybersecurity, network, cidr, check]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [net]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/ip_in_range.go"
---
+12
View File
@@ -0,0 +1,12 @@
package cybersecurity
import "encoding/base64"
// IsBase64 verifica si el string proporcionado es una cadena base64 valida (standard encoding).
func IsBase64(s string) bool {
if len(s) == 0 {
return false
}
_, err := base64.StdEncoding.DecodeString(s)
return err == nil
}
+21
View File
@@ -0,0 +1,21 @@
---
name: is_base64
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func IsBase64(s string) bool"
description: "Valida si un string es una cadena base64 valida segun el encoding estandar."
tags: [cybersecurity, validation, base64, format]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [encoding/base64]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/is_base64.go"
---
+15
View File
@@ -0,0 +1,15 @@
package cybersecurity
// IsHex verifica si el string proporcionado es una cadena hexadecimal valida.
// Requiere longitud par y que todos los caracteres sean digitos hex (0-9, a-f, A-F).
func IsHex(s string) bool {
if len(s) == 0 || len(s)%2 != 0 {
return false
}
for _, c := range s {
if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
return false
}
}
return true
}
+21
View File
@@ -0,0 +1,21 @@
---
name: is_hex
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func IsHex(s string) bool"
description: "Valida si un string es una cadena hexadecimal valida (longitud par, caracteres 0-9 a-f A-F)."
tags: [cybersecurity, validation, hex, format]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/is_hex.go"
---
@@ -0,0 +1,37 @@
package cybersecurity
// JaccardSimilarity calcula la similitud de Jaccard entre dos conjuntos de tokens.
// Devuelve un valor entre 0.0 (sin interseccion) y 1.0 (conjuntos identicos).
func JaccardSimilarity(a, b []string) float64 {
if len(a) == 0 && len(b) == 0 {
return 1.0
}
if len(a) == 0 || len(b) == 0 {
return 0.0
}
setA := make(map[string]struct{}, len(a))
for _, s := range a {
setA[s] = struct{}{}
}
setB := make(map[string]struct{}, len(b))
for _, s := range b {
setB[s] = struct{}{}
}
intersection := 0
for k := range setA {
if _, ok := setB[k]; ok {
intersection++
}
}
// Union = |A| + |B| - |A intersect B| (usando conjuntos sin duplicados)
union := len(setA) + len(setB) - intersection
if union == 0 {
return 0.0
}
return float64(intersection) / float64(union)
}
@@ -0,0 +1,21 @@
---
name: jaccard_similarity
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func JaccardSimilarity(a, b []string) float64"
description: "Calcula la similitud de Jaccard entre dos conjuntos de tokens. Retorna un valor entre 0.0 y 1.0."
tags: [cybersecurity, similarity, jaccard, tokens]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/jaccard_similarity.go"
---
@@ -0,0 +1,49 @@
package cybersecurity
// LevenshteinDistance calcula la distancia de edicion (Levenshtein) entre dos strings.
func LevenshteinDistance(a, b string) int {
ra := []rune(a)
rb := []rune(b)
la := len(ra)
lb := len(rb)
if la == 0 {
return lb
}
if lb == 0 {
return la
}
// Usar solo dos filas para optimizar memoria
prev := make([]int, lb+1)
curr := make([]int, lb+1)
for j := 0; j <= lb; j++ {
prev[j] = j
}
for i := 1; i <= la; i++ {
curr[0] = i
for j := 1; j <= lb; j++ {
cost := 1
if ra[i-1] == rb[j-1] {
cost = 0
}
del := prev[j] + 1
ins := curr[j-1] + 1
sub := prev[j-1] + cost
m := del
if ins < m {
m = ins
}
if sub < m {
m = sub
}
curr[j] = m
}
prev, curr = curr, prev
}
return prev[lb]
}
@@ -0,0 +1,21 @@
---
name: levenshtein_distance
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func LevenshteinDistance(a, b string) int"
description: "Calcula la distancia de edicion de Levenshtein entre dos strings. Util para deteccion de typosquatting."
tags: [cybersecurity, string, distance, typosquatting]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/levenshtein_distance.go"
---
+33
View File
@@ -0,0 +1,33 @@
package cybersecurity
import (
"fmt"
"io"
"net"
"strings"
"time"
)
// LookupWhois realiza una consulta WHOIS para el dominio proporcionado conectandose al servidor whois.iana.org.
func LookupWhois(domain string) (string, error) {
conn, err := net.DialTimeout("tcp", "whois.iana.org:43", 10*time.Second)
if err != nil {
return "", fmt.Errorf("error conectando al servidor WHOIS: %w", err)
}
defer conn.Close()
_ = conn.SetDeadline(time.Now().Add(10 * time.Second))
_, err = fmt.Fprintf(conn, "%s\r\n", domain)
if err != nil {
return "", fmt.Errorf("error enviando consulta WHOIS: %w", err)
}
var sb strings.Builder
_, err = io.Copy(&sb, conn)
if err != nil {
return "", fmt.Errorf("error leyendo respuesta WHOIS: %w", err)
}
return sb.String(), nil
}
+21
View File
@@ -0,0 +1,21 @@
---
name: lookup_whois
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: impure
signature: "func LookupWhois(domain string) (string, error)"
description: "Realiza una consulta WHOIS para un dominio conectandose al servidor whois.iana.org por TCP."
tags: [cybersecurity, io, whois, recon]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [fmt, io, net, strings, time]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/lookup_whois.go"
---
+44
View File
@@ -0,0 +1,44 @@
package cybersecurity
import (
"net/url"
"strings"
)
// trackingParams lista de parametros de tracking comunes a eliminar.
var trackingParams = map[string]bool{
"utm_source": true,
"utm_medium": true,
"utm_campaign": true,
"utm_term": true,
"utm_content": true,
"fbclid": true,
"gclid": true,
"ref": true,
"mc_cid": true,
"mc_eid": true,
}
// NormalizeURL normaliza una URL: convierte el host a minusculas, elimina fragmentos
// y remueve parametros de tracking comunes.
func NormalizeURL(rawURL string) string {
u, err := url.Parse(rawURL)
if err != nil {
return rawURL
}
// Lowercase host
u.Host = strings.ToLower(u.Host)
// Eliminar fragmento
u.Fragment = ""
// Eliminar parametros de tracking
q := u.Query()
for param := range trackingParams {
q.Del(param)
}
u.RawQuery = q.Encode()
return u.String()
}
+21
View File
@@ -0,0 +1,21 @@
---
name: normalize_url
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func NormalizeURL(rawURL string) string"
description: "Normaliza una URL: convierte el host a minusculas, elimina fragmentos y remueve parametros de tracking comunes."
tags: [cybersecurity, url, normalize, sanitize]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [net/url, strings]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/normalize_url.go"
---
+44
View File
@@ -0,0 +1,44 @@
package cybersecurity
import (
"encoding/binary"
"fmt"
"net"
)
// ParseIPCIDR parsea una notacion CIDR y devuelve la direccion de red, broadcast, cantidad de hosts y error.
func ParseIPCIDR(cidr string) (network string, broadcast string, hosts int, err error) {
ip, ipNet, err := net.ParseCIDR(cidr)
if err != nil {
return "", "", 0, fmt.Errorf("CIDR invalido: %w", err)
}
// Solo soportamos IPv4
ip4 := ip.To4()
if ip4 == nil {
return "", "", 0, fmt.Errorf("solo se soporta IPv4")
}
mask := ipNet.Mask
networkIP := ipNet.IP.To4()
network = networkIP.String()
// Calcular broadcast
broadcastIP := make(net.IP, 4)
for i := 0; i < 4; i++ {
broadcastIP[i] = networkIP[i] | ^mask[i]
}
broadcast = broadcastIP.String()
// Calcular hosts usables
netInt := binary.BigEndian.Uint32(networkIP)
bcastInt := binary.BigEndian.Uint32(broadcastIP)
total := int(bcastInt - netInt + 1)
if total > 2 {
hosts = total - 2 // excluir network y broadcast
} else {
hosts = total // /31 o /32
}
return network, broadcast, hosts, nil
}
+21
View File
@@ -0,0 +1,21 @@
---
name: parse_ip_cidr
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func ParseIPCIDR(cidr string) (network string, broadcast string, hosts int, err error)"
description: "Parsea una notacion CIDR IPv4 y devuelve la direccion de red, broadcast y cantidad de hosts usables."
tags: [cybersecurity, network, cidr, parse]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [encoding/binary, fmt, net]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/parse_ip_cidr.go"
---
+15
View File
@@ -0,0 +1,15 @@
package cybersecurity
import (
"fmt"
"net"
)
// ResolveDNS resuelve un hostname a sus direcciones IP usando el resolver del sistema.
func ResolveDNS(host string) ([]string, error) {
ips, err := net.LookupHost(host)
if err != nil {
return nil, fmt.Errorf("error resolviendo DNS para %s: %w", host, err)
}
return ips, nil
}
+21
View File
@@ -0,0 +1,21 @@
---
name: resolve_dns
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: impure
signature: "func ResolveDNS(host string) ([]string, error)"
description: "Resuelve un hostname a sus direcciones IP usando el resolver DNS del sistema."
tags: [cybersecurity, io, dns, resolve]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [fmt, net]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/resolve_dns.go"
---
+34
View File
@@ -0,0 +1,34 @@
package cybersecurity
import (
"fmt"
"net"
"time"
)
// ScanPortTCP intenta conectarse a un puerto TCP y devuelve el estado ("open", "closed", "filtered"),
// un banner si el puerto esta abierto, y un posible error.
func ScanPortTCP(host string, port int, timeoutMs int) (status string, banner string, err error) {
address := fmt.Sprintf("%s:%d", host, port)
timeout := time.Duration(timeoutMs) * time.Millisecond
conn, err := net.DialTimeout("tcp", address, timeout)
if err != nil {
// Distinguir entre conexion rechazada (closed) y timeout (filtered)
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
return "filtered", "", nil
}
return "closed", "", nil
}
defer conn.Close()
// Intentar leer un banner con timeout corto
_ = conn.SetReadDeadline(time.Now().Add(2 * time.Second))
buf := make([]byte, 1024)
n, _ := conn.Read(buf)
if n > 0 {
banner = string(buf[:n])
}
return "open", banner, nil
}
+21
View File
@@ -0,0 +1,21 @@
---
name: scan_port_tcp
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: impure
signature: "func ScanPortTCP(host string, port int, timeoutMs int) (status string, banner string, err error)"
description: "Escanea un puerto TCP en un host dado. Devuelve el estado (open/closed/filtered) y un banner si esta abierto."
tags: [cybersecurity, io, port, scan]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [fmt, net, time]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/scan_port_tcp.go"
---