All posts

C# guide

How to protect a simple Windows C# application with System Locker

A compact Bedrock .NET integration for signed authorization responses and rotating sessions in a Windows desktop application.

By System Locker 8 min read

A small Windows app lives on a machine you do not control, so its licensing check needs more than a direct server answer. This guide uses the Bedrock .NET client to verify signed responses, maintain a live session, and stop protected work when that session ends.

Copy this tutorial and its code examples as plain text for an AI assistant or a clarifying question.

1. Set up a real test system

Create a system in the developer portal, generate a license key, and add a small license-key screen to your application.

For a smoother next launch, save the user's license key in a per-user file below Environment.SpecialFolder.LocalApplicationData, such as %LOCALAPPDATA%\YourApp\license.json, and load it into the license field when the app starts.

2. Add the Bedrock .NET client

Use the official Bedrock .NET client instead of hand-writing the signed-response and heartbeat protocol. Install it with dotnet add package SystemLocker.Bedrock, then pin the signing public key from your developer dashboard in the application.

using SystemLocker.Bedrock;

var client = new BedrockClient(new BedrockConfig
{
    SystemId = "YOUR_20_CHAR_SYSTEM_ID",
    SigningPublicKey = "YOUR_BASE64URL_ED25519_PUBLIC_KEY",
    Version = "1.0.0",
});

client.OnHeartbeatFailure(failure =>
{
    DisableProtectedFeatures();
    ShowAccessError(failure.Error.Message);
});

var auth = await client.AuthenticateWithKeyAsync("CUSTOMER_LICENSE_KEY");
if (!auth.SessionStarted)
{
    ShowAccessError("This license could not be verified.");
    return;
}

EnableProtectedFeatures();

The Bedrock .NET client derives a fault-tolerant hardware identifier by default. You can provide a stable custom value when your application needs one, or set Hwid = "1" only when you deliberately disable device locking. A user moving to a new machine may need a developer-approved hardware reset.

3. Gate the app before showing protected features

Run authentication asynchronously during startup. Bedrock manages the background heartbeat by default, rotates the session token internally, and calls the failure hook once when the live session cannot continue. Keep protected windows or commands unavailable until SessionStarted is true.

if (!auth.SessionStarted)
{
    protectedFeaturesPanel.Enabled = false;
    MessageBox.Show("This license could not be verified.");
    return;
}

protectedFeaturesPanel.Enabled = true;

// When the application exits, end the client session deliberately.
// await client.ShutdownAsync();

If you need a custom scheduler, disable automatic heartbeats and call the client's heartbeat method according to the Bedrock reference. Do not keep using an old token after a failure, and do not turn a temporary network problem into an unbounded retry loop.

4. Keep the security model honest

A desktop client can be modified, which is why the signed Bedrock session matters. Use Program Hash if it fits your release process, do not put high-value secrets in the binary, and make important server-side operations require their own authorization. Bedrock is one reliable layer alongside sound release, update, and backend practices.

When your application grows

The first integration only needs a system, a license key, and a reliable session check. If your application later needs higher limits, expanded authentication logs, more variables, reseller tooling, or higher-tier Aegis IP Intelligence, those capabilities can follow when the operational need is real.

Ready to try Bedrock in your C# app?

Create a system, pin its signing key, and protect a simple Windows feature with the official Bedrock .NET client.