EV.DataProtection.NetStandard
2.0.0
dotnet add package EV.DataProtection.NetStandard --version 2.0.0
NuGet\Install-Package EV.DataProtection.NetStandard -Version 2.0.0
<PackageReference Include="EV.DataProtection.NetStandard" Version="2.0.0" />
<PackageVersion Include="EV.DataProtection.NetStandard" Version="2.0.0" />
<PackageReference Include="EV.DataProtection.NetStandard" />
paket add EV.DataProtection.NetStandard --version 2.0.0
#r "nuget: EV.DataProtection.NetStandard, 2.0.0"
#:package EV.DataProtection.NetStandard@2.0.0
#addin nuget:?package=EV.DataProtection.NetStandard&version=2.0.0
#tool nuget:?package=EV.DataProtection.NetStandard&version=2.0.0
EV.DataProtection.NetStandard
Una librería simple y segura para .NET Standard 2.0 que gestiona la protección de datos sensibles usando ASP.NET Data Protection API con soporte para expiración temporal y validación automática.
🌟 Características
- ✅ Compatible con múltiples plataformas: .NET Framework 4.6.1+, .NET Core 2.0+, .NET 5, .NET 6 y .NET 7
- 🔒 Cifrado robusto: Basado en ASP.NET Core Data Protection API
- ⏰ Expiración automática: Protección de datos con tiempo de vida configurable
- 🔧 Configuración flexible: Soporta inyección de dependencias y configuración tradicional
- 📝 Logging integrado: Seguimiento completo de operaciones
- 🎯 API unificada: Misma interfaz para todas las plataformas
- 🚀 Fácil de usar: Patrón Manager para aplicaciones sin DI
📦 Instalación
Instalación Rápida
Install-Package EV.DataProtection.NetStandard
O usando .NET CLI:
dotnet add package EV.DataProtection.NetStandard
Instalación Manual de Dependencias
Si prefieres instalar manualmente cada paquete:
# Package Manager Console
Install-Package Microsoft.AspNetCore.DataProtection -Version 6.0.36
Install-Package Microsoft.Extensions.DependencyInjection -Version 6.0.2
Install-Package Microsoft.Extensions.Logging -Version 6.0.1
Install-Package Microsoft.Extensions.Logging.Console -Version 6.0.1
Install-Package System.Configuration.ConfigurationManager -Version 6.0.2
Install-Package System.Text.Json -Version 6.0.11
# .NET CLI
dotnet add package Microsoft.AspNetCore.DataProtection --version 6.0.36
dotnet add package Microsoft.Extensions.DependencyInjection --version 6.0.2
dotnet add package Microsoft.Extensions.Logging --version 6.0.1
dotnet add package Microsoft.Extensions.Logging.Console --version 6.0.1
dotnet add package System.Configuration.ConfigurationManager --version 6.0.2
dotnet add package System.Text.Json --version 6.0.11
🚀 Guía de Inicio Rápido
Configuración para .NET Framework 4.8
1. Configurar app.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="DataProtection:Enabled" value="true" />
<add key="DataProtection:DataProtectionSecret" value="mSW*9&HJ8Gud6RAhWT*Rux4nYC7CKu7DKzn2SnkY4@d2-gUP%MK#TH" />
<add key="DataProtection:DataProtectionRedirectUrl" value="https://midominio.com/redirect" />
<add key="DataProtection:DataProtectionTimeLifeHours" value="1" />
</appSettings>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Extensions.DependencyInjection"
publicKeyToken="adb9793829ddae60" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.2" newVersion="6.0.0.2" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Extensions.Logging.Abstractions"
publicKeyToken="adb9793829ddae60" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.4" newVersion="6.0.0.4" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Json"
publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.11" newVersion="6.0.0.11" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
2. Ejemplo de uso básico
using EV.DataProtection.NetStandard.Helpers;
using EV.DataProtection.NetStandard.Options;
using EV.DataProtection.NetStandard.Services;
using System;
namespace EV.DataProtection.NetStandard.Test
{
internal class Program
{
private static void Main(string[] args)
{
Console.WriteLine("=== DataProtection para .NET Framework 4.8 ===\n");
try
{
// Ejemplo 1: Uso básico con Singleton
Console.WriteLine("1. Uso básico:");
string originalText = "EVI - Hola mundo...!!!";
Console.WriteLine($"Texto original: {originalText}");
Console.WriteLine();
string protectedText = DataProtectionHelper.Protect(originalText);
Console.WriteLine($"Texto protegido: {protectedText}");
Console.WriteLine();
string unprotectedText = DataProtectionHelper.Unprotect(protectedText);
Console.WriteLine($"Texto desprotegido: {unprotectedText}");
Console.WriteLine();
Console.WriteLine();
// Ejemplo 2: Protección con tiempo limitado
Console.WriteLine("2. Protección con tiempo limitado (2 horas):");
string timedProtected = DataProtectionHelper.ProtectToTimeLimited(
"EVI - Hola mundo...!!! (Datos con tiempo límite)", 2);
Console.WriteLine($"Datos protegidos (2h): {timedProtected}");
Console.WriteLine();
var timedResult = DataProtectionHelper.UnprotectToTimeLimited(timedProtected);
Console.WriteLine($"Resultado: Success={timedResult.IsSuccess}, Data={timedResult.Data}");
Console.WriteLine();
Console.WriteLine();
// Ejemplo 3: Configuración personalizada
Console.WriteLine("3. Configuración personalizada:");
var customConfig = new DataProtectionConfiguration
{
DataProtectionSecret = "mSW*9&HJ8Gud6RAhWT*Rux4nYC7CKu7DKzn2SnkY4@d2-gUP%MK#TH",
DataProtectionRedirectUrl = "https://ejemplo.com/custom",
DataProtectionTimeLifeHours = 1,
Enabled = true
};
var customManager = new DataProtectionManager(customConfig);
var customProtected = customManager.Protect("Texto con configuración personalizada");
var customUnprotected = customManager.Unprotect(customProtected);
Console.WriteLine("Config personalizada - Original: Texto con configuración personalizada");
Console.WriteLine($"Config personalizada - Protegido: {customProtected}");
Console.WriteLine($"Config personalizada - Desprotegido: {customUnprotected}");
Console.WriteLine();
// Ejemplo 4: Manejo de errores
Console.WriteLine("4. Manejo de errores:");
try
{
DataProtectionHelper.Unprotect("texto-invalido-que-causara-error");
}
catch (Exception ex)
{
Console.WriteLine($"Error esperado: {ex.Message}");
}
Console.WriteLine("\n=== Ejemplos completados exitosamente ===");
}
catch (Exception ex)
{
Console.WriteLine($"Error general: {ex.Message}");
Console.WriteLine($"Stack trace: {ex.StackTrace}");
}
Console.WriteLine("\nPresiona cualquier tecla para salir...");
Console.ReadKey();
}
}
}
Para .NET Core / .NET 5, .NET 6 y .NET 7 (appsettings.json)
{
"DataProtectionConfiguration": {
"Enabled": true,
"DataProtectionSecret": "mi-super-secreto-muy-largo-y-seguro-123456789",
"DataProtectionRedirectUrl": "https://midominio.com/redirect",
"DataProtectionTimeLifeHours": 1
}
}
using EV.DataProtection.NetStandard.Extensions;
using EV.DataProtection.NetStandard.Interfaces;
// Program.cs (.NET 6+)
var builder = WebApplication.CreateBuilder(args);
// Agregar el servicio
builder.Services.AddDataProtectionService(builder.Configuration);
var app = builder.Build();
// Usar en controladores o servicios
app.MapGet("/protect/{text}", (string text, IDataProtectionService dataProtection) =>
{
var protected = dataProtection.Protect(text);
var unprotected = dataProtection.Unprotect(protected);
return new {
Original = text,
Protected = protected,
Unprotected = unprotected
};
});
app.Run();
🔧 Configuración Avanzada
Configuración Personalizada
using EV.DataProtection.NetStandard.Options;
using EV.DataProtection.NetStandard.Services;
// Crear configuración personalizada
var customConfig = new DataProtectionConfiguration
{
DataProtectionSecret = "mi-secreto-personalizado-de-al-menos-20-caracteres",
DataProtectionRedirectUrl = "https://miapp.com/error",
DataProtectionTimeLifeHours = 7,
Enabled = true
};
// Usar con Manager personalizado
var customManager = new DataProtectionManager(customConfig);
string protected = customManager.Protect("Datos con config personalizada");
string unprotected = customManager.Unprotect(protected);
Inyección de Dependencias (.NET Core)
// Startup.cs o Program.cs
services.AddDataProtectionService(configuration);
// En un controlador
[ApiController]
[Route("api/[controller]")]
public class SecureController : ControllerBase
{
private readonly IDataProtectionService _dataProtection;
public SecureController(IDataProtectionService dataProtection)
{
_dataProtection = dataProtection;
}
[HttpPost("protect")]
public IActionResult ProtectData([FromBody] string data)
{
try
{
var protectedData = _dataProtection.Protect(data);
return Ok(new { ProtectedData = protectedData });
}
catch (Exception ex)
{
return BadRequest(new { Error = ex.Message });
}
}
[HttpPost("protect-timed")]
public IActionResult ProtectTimedData([FromBody] TimedDataRequest request)
{
try
{
var protectedData = _dataProtection.ProtectToTimeLimited(
request.Data,
request.Hours);
return Ok(new { ProtectedData = protectedData });
}
catch (Exception ex)
{
return BadRequest(new { Error = ex.Message });
}
}
}
public class TimedDataRequest
{
public string Data { get; set; }
public double Hours { get; set; }
}
📊 Ejemplos de Uso por Plataforma
.NET Framework 4.8 (Windows Forms)
using EV.DataProtection.NetStandard.Helpers;
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void btnProtect_Click(object sender, EventArgs e)
{
try
{
string original = txtOriginal.Text;
string protected = DataProtectionHelper.Protect(original);
txtProtected.Text = protected;
// Verificar desprotección
string unprotected = DataProtectionHelper.Unprotect(protected);
txtUnprotected.Text = unprotected;
}
catch (Exception ex)
{
MessageBox.Show($"Error: {ex.Message}", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
ASP.NET Web API (.NET Framework)
using EV.DataProtection.NetStandard.Helpers;
public class SecureApiController : ApiController
{
[HttpPost]
[Route("api/secure/protect")]
public IHttpActionResult ProtectData([FromBody] string data)
{
try
{
var protectedData = DataProtectionHelper.Protect(data);
return Ok(new { ProtectedData = protectedData });
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
[HttpPost]
[Route("api/secure/unprotect")]
public IHttpActionResult UnprotectData([FromBody] string protectedData)
{
try
{
var originalData = DataProtectionHelper.Unprotect(protectedData);
return Ok(new { OriginalData = originalData });
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
}
Xamarin (Multiplataforma)
using EV.DataProtection.NetStandard.Options;
using EV.DataProtection.NetStandard.Services;
public class SecureDataService
{
private readonly DataProtectionManager _manager;
public SecureDataService()
{
var config = new DataProtectionConfiguration
{
DataProtectionSecret = "xamarin-app-secret-key-123456789012345",
DataProtectionRedirectUrl = "app://error",
DataProtectionTimeLifeHours = 24
};
_manager = new DataProtectionManager(config);
}
public string ProtectUserData(string userData)
{
return _manager.Protect(userData);
}
public string UnprotectUserData(string protectedData)
{
return _manager.Unprotect(protectedData);
}
public bool ValidateTimedToken(string token)
{
var result = _manager.UnprotectToTimeLimited(token);
return result.IsSuccess;
}
}
🔒 Casos de Uso Comunes
Protección de Tokens de Sesión
using System.Text.Json;
public class SessionManager
{
public string CreateSessionToken(string userId, int sessionHours = 24)
{
var sessionData = new
{
UserId = userId,
CreatedAt = DateTimeOffset.UtcNow,
SessionId = Guid.NewGuid().ToString()
};
string jsonData = JsonSerializer.Serialize(sessionData);
return DataProtectionHelper.ProtectToTimeLimited(jsonData, sessionHours);
}
public (bool IsValid, string UserId) ValidateSessionToken(string token)
{
var result = DataProtectionHelper.UnprotectToTimeLimited(token);
if (!result.IsSuccess)
return (false, string.Empty);
try
{
var sessionData = JsonSerializer.Deserialize<dynamic>(result.Data);
return (true, sessionData.UserId.ToString());
}
catch
{
return (false, string.Empty);
}
}
}
Protección de Datos Sensibles en Base de Datos
public class UserRepository
{
public void SaveUserSensitiveData(int userId, string sensitiveData)
{
string protectedData = DataProtectionHelper.Protect(sensitiveData);
// Guardar en base de datos
// db.Users.Update(userId, protectedData);
}
public string GetUserSensitiveData(int userId)
{
// Obtener de base de datos
// string protectedData = db.Users.GetProtectedData(userId);
return DataProtectionHelper.Unprotect(protectedData);
}
}
Protección de URLs con Parámetros Sensibles
using System.Text;
using System.Text.Json;
public class SecureUrlGenerator
{
public string GenerateSecureUrl(string baseUrl, object parameters, double validHours = 1)
{
string jsonParams = JsonSerializer.Serialize(parameters);
string protectedParams = DataProtectionHelper.ProtectToTimeLimited(jsonParams, validHours);
string encodedParams = Convert.ToBase64String(Encoding.UTF8.GetBytes(protectedParams));
return $"{baseUrl}?token={Uri.EscapeDataString(encodedParams)}";
}
public (bool IsValid, T Parameters) ValidateSecureUrl<T>(string token)
{
try
{
byte[] tokenBytes = Convert.FromBase64String(Uri.UnescapeDataString(token));
string protectedParams = Encoding.UTF8.GetString(tokenBytes);
var result = DataProtectionHelper.UnprotectToTimeLimited(protectedParams);
if (!result.IsSuccess)
return (false, default(T));
T parameters = JsonSerializer.Deserialize<T>(result.Data);
return (true, parameters);
}
catch
{
return (false, default(T));
}
}
}
⚙️ Configuración de Seguridad
Requisitos del Secreto
El DataProtectionSecret debe cumplir:
- Longitud: Entre 20 y 256 caracteres
- Caracteres permitidos: Alfanuméricos y símbolos especiales
- Unicidad: Diferente para cada aplicación/entorno
- Confidencialidad: Nunca almacenar en código fuente
Ejemplo de Secretos Seguros
// ❌ MALO - Muy corto, predecible
"password123"
// ❌ MALO - Información predecible
"MyApp2025Secret"
// ✅ BUENO - Largo, aleatorio, caracteres mixtos
"K9#mX2$vL8@nB4!qW6*jR1&sD5^fH3+pA7~nC0%gT9#uY8@xE4!mZ6*oV3&lN2^qS5+wQ1~rU7%kI9#hG8@bT4!"
// ✅ BUENO - Generado con herramientas criptográficas
"mSW*9&HJ8Gud6RAhWT*Rux4nYC7CKu7DKzn2SnkY4@d2-gUP%MK#TH"
Generación de Secretos Seguros
using System.Security.Cryptography;
using System.Linq;
public static string GenerateSecureSecret(int length = 64)
{
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+-=[]{}|;:,.<>?";
using (var rng = new RNGCryptoServiceProvider())
{
var bytes = new byte[length];
rng.GetBytes(bytes);
return new string(bytes.Select(b => chars[b % chars.Length]).ToArray());
}
}
🚨 Troubleshooting
Errores Comunes
Error: "DataProtectionSecret is required"
Solución: Verificar que el secreto esté configurado en app.config o appsettings.json
Error: "DataProtectionSecret must be between 20 and 256 characters"
Solución: Usar un secreto más largo (mínimo 20 caracteres)
Error: "Token has expired"
Solución: El token protegido ha expirado, generar uno nuevo
Error: "Error unprotecting data"
Solución: Verificar que se esté usando el mismo secreto para proteger y desproteger
Problemas de Referencias en .NET Framework
Error: "Could not load file or assembly 'Microsoft.Extensions.DependencyInjection'"
Solución: Agregar binding redirects en app.config/web.config (ver ejemplo en sección de configuración)
Error: "The type initializer for 'Microsoft.AspNetCore.DataProtection' threw an exception"
# Reinstalar paquetes en Package Manager Console
Update-Package -Reinstall
Error: "System.IO.FileNotFoundException: Could not load file or assembly 'System.Memory'"
<PackageReference Include="System.Memory" Version="4.5.5" />
Error en tiempo de ejecución con .NET Framework 4.6.1
# Solución: Agregar paquetes adicionales
Install-Package System.Runtime.CompilerServices.Unsafe -Version 6.0.0
Install-Package System.Buffers -Version 4.5.1
Verificación de Referencias
Para verificar que todas las referencias estén correctas:
# En Package Manager Console
Get-Package | Where-Object { $_.Id -like "*Microsoft.Extensions*" -or $_.Id -like "*DataProtection*" }
Deberías ver:
Id Version
-- -------
Microsoft.AspNetCore.DataProtection 6.0.36
Microsoft.Extensions.DependencyInjection 6.0.2
Microsoft.Extensions.Logging 6.0.1
Microsoft.Extensions.Logging.Console 6.0.1
System.Configuration.ConfigurationManager 6.0.2
System.Text.Json 6.0.11
Logging y Diagnóstico
// Habilitar logging detallado
services.AddLogging(builder =>
{
builder.AddConsole();
builder.AddDebug();
builder.SetMinimumLevel(LogLevel.Debug);
});
🔄 Migración desde Otras Versiones
Desde EV.DataProtection (.NET 8)
Los datos protegidos son compatibles entre versiones si se usa el mismo secreto:
// Datos protegidos con .NET 8
string protectedData = ".NET8_protected_data_here";
// Se pueden desproteger con .NET Standard 2.0
string originalData = DataProtectionHelper.Unprotect(protectedData);
Migración de Configuración
.NET 8 → .NET Standard 2.0
// appsettings.json (.NET 8)
{
"DataProtectionConfiguration": {
"DataProtectionSecret": "mi-secreto"
}
}
<appSettings>
<add key="DataProtection:DataProtectionSecret" value="mi-secreto" />
</appSettings>
📋 Compatibilidad
| Plataforma | Versión | Compatible |
|---|---|---|
| .NET Framework | 4.6.1+ | ✅ |
| .NET Core | 2.0+ | ✅ |
| .NET | 5+, 6+, 7+ | ✅ |
| Xamarin.iOS | 10.14+ | ✅ |
| Xamarin.Android | 8.0+ | ✅ |
| Xamarin.Mac | 3.8+ | ✅ |
| Unity | 2018.1+ | ✅ |
📝 Licencia
Copyright © 2025 EV. Todos los derechos reservados.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.AspNetCore.DataProtection (>= 6.0.36)
- Microsoft.Extensions.DependencyInjection (>= 6.0.2)
- Microsoft.Extensions.Logging (>= 6.0.1)
- Microsoft.Extensions.Logging.Console (>= 6.0.1)
- System.Configuration.ConfigurationManager (>= 6.0.2)
- System.Memory (>= 4.5.5)
- System.Text.Json (>= 6.0.11)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.0 | 208 | 9/30/2025 |
🎉 Lanzamiento .NET Standard 2.0
✨ Características de Data Protection:
• Compatible con .NET Framework 4.6.1+, .NET Core 2.0+, .NET 5 y .NET 6
• Configuración simple con inyección de dependencias
• Soporte para configuración tradicional (app.config/web.config)
• Protección con expiración configurable
• Patrón Manager para aplicaciones sin DI
• Manejo elegante de errores
• Logging comprehensivo
• API unificada para múltiples plataformas
• Para .NET 8+ se recomienda usar la version EV.DataProtection 8.0.0
🔧 Compatibilidad:
• .NET Framework 4.6.1+, 4.7+, 4.8+
• .NET Core 2.0, 2.1, 2.2, 3.0, 3.1
• .NET 5, 6, 7
• Xamarin
• Unity (2018.1+)