Licencia por suscripción con código Pro cifrado
Una licencia por suscripción de duración limitada con un período de gracia, en la que el código reservado a la suscripción se protege con el cifrado de código de Babel Obfuscator.
Las suscripciones necesitan dos comportamientos que una simple fecha de caducidad no ofrece: un período de gracia, para que a los clientes que pagan no se les corte el servicio en el instante en que una renovación se retrasa, y un control que no se pueda eludir editando un archivo de configuración. Este ejemplo hace las dos cosas, y liga la funcionalidad premium («pro») a la suscripción con el Cifrado de código: el método pro solo se ejecuta mientras la suscripción, incluido su margen de gracia, es válida, porque la máquina virtual de Babel obtiene de la licencia su contraseña de descifrado.
Ejemplo de código
git clone https://github.com/babelfornet/subscription-license-console-example.gitProSuite es una aplicación de consola con una función básica gratuita y una función pro cifrada;
LicenseGenerator emite licencias por suscripción con duración y gracia configurables.
Dos fechas: renovación y fecha límite definitiva
La licencia lleva dos fechas:
- la
ExpireDateque aplica el motor, establecida en el final del período de gracia (la fecha límite definitiva), y - un campo informativo
subscription-endque marca cuándo hay que renovar.
DateTime subscriptionEnd = now.AddDays(days); // soft end — renewal due
DateTime hardCutoff = subscriptionEnd.AddDays(grace); // engine-enforced end of grace
var license = new StringLicense { ExpireDate = hardCutoff };
license
.ForAssembly(assemblyFullName)
.WithUniqueId("SUBSCR-")
.WithHardwareKey(HardwareId.Create().ToMachineKey())
.WithField(Secrets.SubscriptionEndField, subscriptionEnd.ToString("O"))
.WithField(Secrets.ProSource, Secrets.ProPassword.Encrypt(Secrets.FieldSecret))
.LicensedTo("Demo Customer", "demo@example.com", "ACME Corp");Babel Licensing rechaza la licencia automáticamente una vez pasada ExpireDate, así que la
fecha límite definitiva no necesita código propio. La aplicación solo tiene que distinguir entre
activa y en gracia, y lo hace comparando el campo informativo subscription-end con la hora
actual:
var now = DateTime.UtcNow;
if (subEnd.HasValue && now > subEnd.Value)
{
int graceDaysLeft = (int)Math.Ceiling(((license.ExpireDate ?? now) - now).TotalDays);
return new SubscriptionStatus(SubscriptionState.Grace, subEnd, graceDaysLeft,
$"Subscription lapsed — grace period active ({graceDaysLeft} day(s) left). Please renew.");
}La función pro cifrada
El método pro está cifrado; su contraseña procede de la licencia a través del hook get password.
Eso es lo que liga el código cifrado a la suscripción: mientras la licencia supera la validación
(activa o en gracia), el hook devuelve la contraseña y el método se ejecuta; una vez pasada la
fecha límite definitiva, Validate() lanza una excepción y el hook ya no puede proporcionar la
contraseña.
[Obfuscation(Feature = "msil encryption:internal=true;source=pro;password=Pr0-Su1te-2026-K3y", Exclude = false)]
public static string Forecast(double[] series) { /* premium analytics */ }
[Obfuscation(Feature = "msil encryption get password")]
internal static string GetSourcePassword(string source)
{
var license = Validate(); // throws once past the end of grace
var field = license.Fields.FirstOrDefault(f => f.Name == source)
?? throw new InvalidOperationException($"License does not grant source '{source}'.");
return field.Value.Decrypt(Secrets.FieldSecret);
}Ejecución
# Build in Release — Babel encrypts Pro.Forecast.
dotnet build src/ProSuite/ProSuite.csproj -c Release
# Mint a subscription license: active for 30 days, 7-day grace.
dotnet run --project src/LicenseGenerator -- --days 30 --grace 7
cp ProSuite.lic src/ProSuite/bin/Release/net8.0/
dotnet src/ProSuite/bin/Release/net8.0/ProSuite.dllVuelva a emitir la licencia para recorrer todos los estados:
dotnet run --project src/LicenseGenerator -- --days -2 --grace 7 # lapsed, in grace
dotnet run --project src/LicenseGenerator -- --expired # past grace| Estado | Condición | Función pro |
|---|---|---|
| Activa | antes del final de la suscripción | se ejecuta |
| En gracia | pasado el final de la suscripción, antes de la fecha límite definitiva | se ejecuta, con un aviso de renovación |
| Caducada | pasada la fecha límite definitiva | bloqueada: la BVM no puede descifrarla |
Pasado el período de gracia, la aplicación lo demuestra intentando llamar de todos modos al método pro:
Subscription expired: License expired
Basic average: 13.63
Pro forecast is locked. Renew your subscription to restore access.
(proof) encrypted Pro.Forecast blocked: License expiredPara la facturación periódica, lo normal es que la misma licencia la emita y la renueve el Babel Licensing Service, que puede acortar el período de validez y enviar las renovaciones automáticamente. La licencia de archivo sin conexión que se muestra aquí es la manera más sencilla de mostrar las transiciones entre activa, en gracia y caducada.
keys.pem y las contraseñas del ejemplo son solo para demostración. Mantenga la clave privada
RSA sin conexión y emita las licencias desde el lado del proveedor de software; con la aplicación
solo se distribuye la clave pública.