Licensify 1.0.2

dotnet add package Licensify --version 1.0.2
                    
NuGet\Install-Package Licensify -Version 1.0.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Licensify" Version="1.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Licensify" Version="1.0.2" />
                    
Directory.Packages.props
<PackageReference Include="Licensify" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Licensify --version 1.0.2
                    
#r "nuget: Licensify, 1.0.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Licensify@1.0.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Licensify&version=1.0.2
                    
Install as a Cake Addin
#tool nuget:?package=Licensify&version=1.0.2
                    
Install as a Cake Tool

Licensify — C# / .NET SDK

Licensify 라이센스 인증을 가장 간단하게 붙이는 C# / .NET 라이브러리입니다.

복잡한 건 전부 SDK 안에 있습니다. 암호화 키 교환, 서버 신원 검증, 세션 유지(하트비트), 재시도까지 SDK가 알아서 처리하므로 여러분은 AuthenticateAsync 하나만 호출하면 됩니다. 라이센스 키만 넘기면 곧바로 인증된 세션을 받습니다. 연동은 몇 줄이면 충분합니다.

라이센스 발급, 소프트웨어 등록, 세션·사용 현황 관리는 모두 관리자 홈페이지 licensify.kr 에서 합니다. 이 SDK는 거기서 발급한 라이센스를 여러분의 앱에서 인증하는 클라이언트입니다.

요구 사항

  • .NET 8.0 이상 (HKDF는 .NET 5+ 필요, new AesGcm(key, 16)은 .NET 8의 태그 크기 지정 형식).
  • BouncyCastle.Cryptography 2.4.0 — X25519와 Ed25519는 .NET 기본 라이브러리(BCL)에 없습니다.

설치

dotnet add package Licensify

빠른 시작

using Licensify;

await using var client = new LicenseClient(
    appId: "myapp",        // 플랫폼 소프트웨어 ID (≤ 10자)
    clientVersion: "1.2.0" // 앱 버전 (≤ 20자)
);

try
{
    Session session = await client.AuthenticateAsync(userEnteredLicenseKey);

    Console.WriteLine($"인증됨. 남은 시간 {session.RemainingMillis} ms.");
    Console.WriteLine($"theme = {session.LocalVariables.GetValueOrDefault("theme")}");

    // ... 앱 실행; 하트비트 루프가 세션을 자동으로 살아있게 유지합니다 ...

    await session.SetLocalVariableAsync("highscore", "9001");
}
catch (LicenseException ex)
{
    // 모든 실패는 이 한 타입으로 흐릅니다. ex.Code로 분기하세요.
    switch (ex.Code)
    {
        case LicenseErrorCode.LicenseBanned:
            Console.WriteLine($"정지됨: {ex.Reason} (해제 시각 {ex.Until})");
            break;
        case LicenseErrorCode.UpdateRequired:
            Console.WriteLine($"{ex.LatestVersion}(으)로 업데이트하세요: {ex.DownloadUrl}");
            break;
        case LicenseErrorCode.NetworkError when ex.Retryable:
            Console.WriteLine("네트워크 문제 — 다시 시도하세요.");
            break;
        default:
            Console.WriteLine($"{ex.Code}: {ex.Message}");
            break;
    }
}
// DisposeAsync()가 빠져나갈 때 세션을 (best-effort로) 해제합니다.

옵션과 함께

모든 옵션은 선택 사항이며, 커스터마이즈 가능한("OPEN") 영역만 다룹니다. 보안과 관련된 모든 것은 SDK 내부에 잠겨 있습니다.

var client = new LicenseClient("myapp", "1.2.0", new LicenseClientOptions
{
    FileHash = sha256OfMyBinary,             // 선택적 무결성 검사 (≤ 64자)
    AutoReauthenticate = true,               // 세션 상실 시 1회 자동 재인증
    OnSessionLost = err => LockTheApp(err),  // 세션 도중 하트비트 실패 / 만료 / 정지
    OnUpdateRequired = info => ShowUpdatePrompt(info.LatestVersion, info.DownloadUrl),
    Logger = (level, msg) => Console.WriteLine($"[{level}] {msg}"), // 비밀값은 절대 로깅하지 않음
    UserAgentSuffix = "MyApp",               // 서버 로깅용으로 User-Agent에 덧붙임
});

공개 API

// 생성 — 서버 URL과 서명 키는 내부 상수이며 인자로 받지 않습니다.
new LicenseClient(string appId, string clientVersion, LicenseClientOptions? options = null);

Task<Session> AuthenticateAsync(string licenseKey, CancellationToken ct = default);
Task          ReleaseAsync(CancellationToken ct = default);   // best-effort, 멱등
bool          IsActive { get; }

// Session — 사용에 필요한 부분만; 모든 암호 상태는 숨겨져 있습니다.
long                          Session.RemainingMillis;   // 권위값, remainMs 기반
IReadOnlyDictionary<string,string> Session.LocalVariables;
IReadOnlyDictionary<string,string> Session.GlobalVariables;
string                        Session.LatestVersion;
string                        Session.Exp;               // 표시 전용
string                        Session.ServerTime;        // 표시 전용
Task Session.SetLocalVariableAsync(string key, string value, CancellationToken ct = default);

클라이언트는 IAsyncDisposable/IDisposable입니다. await using을 쓰면 스코프가 끝날 때 세션이 해제됩니다. 전역 종료 훅은 등록하지 않으므로, 앱 종료 시 직접 ReleaseAsync()(또는 dispose)를 호출하세요. 해제하지 못한 채 프로세스가 죽어도 서버의 60초 세션 TTL이 정리합니다.

에러 코드

모든 실패는 LicenseException으로 흐릅니다. Code(LicenseErrorCode)로 분기하고, Retryable·Context와 편의 접근자(Reason, Until, LatestVersion, DownloadUrl)를 사용하세요. ServerCode에는 원본 서버 코드(예: "SDK_102")가 로깅용으로 담깁니다. 전체 목록과 서버 코드 매핑은 LicenseErrorCode를 참고하세요.

보안 (요약)

  • 서버는 자기만 아는 키로 응답에 서명하고, SDK가 내장된 공개키로 검증 → 가짜 서버·중간자(MITM) 차단
  • 매 세션 일회용 키로 AES-256-GCM 암호화 + 시퀀스 기반 재전송 방지

⚠️ 앱 자체 보호는 개발자 몫입니다

SDK는 통신을 안전하게 만들지만 여러분의 빌드된 앱을 보호하진 못합니다. 공격자가 여러분 바이너리에서 AuthenticateAsync 호출이나 그 결과를 검사하는 분기(if)·해시 검사 자체를 뜯어내면 SDK가 막을 길이 없습니다 — 그건 SDK가 아니라 여러분의 코드이기 때문입니다. 그래서:

  • 배포 바이너리는 반드시 난독화하세요
  • 인증·무결성 검사를 한 곳에 몰지 말고 여러 군데에 흩어 넣으세요
  • 검사 결과를 우회하기 어렵게 설계하세요
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
1.0.2 91 8/9/2026

서버 프로토콜 v2.4 대응: init 응답의 keyId로 검증 공개키를 선택하도록 변경(6필드 서명). 구버전은 최신 서버에서 init 검증에 실패하므로 업데이트가 필요합니다.