using System.Security.Cryptography; using System.Text; namespace Nuuru.Server.Utilities { public static class IpCloaker { /// /// Cloaks an IPv4 address so that each segment's output depends on all preceding segments. /// Two IPs sharing a prefix (e.g. same /24) will share the same cloaked prefix. /// public static string Cloak(string ipAddress, byte[] key) { if (string.IsNullOrEmpty(ipAddress)) return ipAddress; var parts = ipAddress.Split('.'); if (parts.Length != 4) return CloakNonIpv4(ipAddress, key); var octets = new byte[4]; for (int i = 0; i < 4; i++) { if (!byte.TryParse(parts[i], out octets[i])) return CloakNonIpv4(ipAddress, key); } var segments = new string[4]; using var hmac = new HMACSHA256(key); for (int i = 0; i < 4; i++) { var hash = hmac.ComputeHash(octets, 0, i + 1); segments[i] = Convert.ToHexString(hash, 0, 2).ToLowerInvariant(); } return string.Join(":", segments); } /// /// Fallback for IPv6 or other formats — hash the whole thing. /// private static string CloakNonIpv4(string ipAddress, byte[] key) { using var hmac = new HMACSHA256(key); var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(ipAddress)); return Convert.ToHexString(hash, 0, 8).ToLowerInvariant(); } } }