{"id":37037536,"url":"https://github.com/12noonllc/licensemanagerx","last_synced_at":"2026-04-26T19:01:04.130Z","repository":{"id":235306036,"uuid":"782207493","full_name":"12noonLLC/LicenseManagerX","owner":"12noonLLC","description":"Windows GUI front-end for Standard.Licensing project with optional enhanced API for applications","archived":false,"fork":false,"pushed_at":"2026-04-22T01:40:06.000Z","size":1291,"stargazers_count":45,"open_issues_count":3,"forks_count":15,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-04-22T03:30:14.980Z","etag":null,"topics":["license","license-management","licenses","licensing"],"latest_commit_sha":null,"homepage":"https://12noon.com","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/12noonLLC.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-04-04T20:59:40.000Z","updated_at":"2026-04-22T01:38:48.000Z","dependencies_parsed_at":"2026-03-05T11:03:22.491Z","dependency_job_id":null,"html_url":"https://github.com/12noonLLC/LicenseManagerX","commit_stats":null,"previous_names":["skst/licensemanager","12noonllc/licensemanager","12noonllc/licensemanagerx"],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/12noonLLC/LicenseManagerX","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/12noonLLC%2FLicenseManagerX","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/12noonLLC%2FLicenseManagerX/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/12noonLLC%2FLicenseManagerX/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/12noonLLC%2FLicenseManagerX/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/12noonLLC","download_url":"https://codeload.github.com/12noonLLC/LicenseManagerX/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/12noonLLC%2FLicenseManagerX/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32308878,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T17:23:19.671Z","status":"ssl_error","status_checked_at":"2026-04-26T17:23:19.195Z","response_time":129,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["license","license-management","licenses","licensing"],"created_at":"2026-01-14T04:28:10.506Z","updated_at":"2026-04-26T19:01:04.104Z","avatar_url":"https://github.com/12noonLLC.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# License Manager X by [12noon LLC](https://12noon.com)\n\n[![](https://img.shields.io/github/v/release/12noonLLC/LicenseManagerX.svg?label=latest%20release\u0026color=007edf)](https://github.com/12noonLLC/LicenseManagerX/releases/latest)\n[![build](https://github.com/12noonLLC/LicenseManagerX/actions/workflows/build.yml/badge.svg)](https://github.com/12noonLLC/LicenseManagerX/actions/workflows/build.yml)\n[![GitHub last commit](https://img.shields.io/github/last-commit/12noonLLC/LicenseManagerX)](https://github.com/12noonLLC/LicenseManagerX)\n\n[![NuGet Version](https://img.shields.io/nuget/v/LicenseManager_12noon.Client.svg?style=for-the-badge)](https://nuget.org/packages/LicenseManager_12noon.Client)\n[![NuGet Downloads](https://img.shields.io/nuget/dt/LicenseManager_12noon.Client.svg?style=for-the-badge)](https://nuget.org/packages/LicenseManager_12noon.Client)\n\n## Description\n\nThis project ensures that software licenses are securely generated and validated,\nproviding a robust mechanism for software protection.\n\n### Secret Model\n\n- `.private` files contain secret material (private key + passphrase context) and must be protected.\n- `.lic` files are intended for distribution to licensees.\n- Product ID and public key are not secrets.\n\nFor this repository, the `.private` file inside `LicenseManagerX_Example` is intentionally included as an inspectable example only.\nDo not treat that as a general practice for real applications.\n\n**License Manager X** is a graphical front-end application designed to create and manage\nlicenses for software applications using .NET.\nIt leverages the [Standard.Licensing](https://github.com/junian/Standard.Licensing)\nproject to handle license generation and validation.\n\nIn addition to this Windows application, License Manager X can also be used\nfrom a command line to support scripting, etc.\n\nYour application will need to either:\n- Use the [LicenseManager_12noon.Client](https://nuget.org/packages/LicenseManager_12noon.Client) NuGet package, which has an improved API to validate licenses for your .NET application.\n- Use the original **Standard.Licensing** NuGet package on which it is based.\n\nYou can switch at any time--you are not locked in to one or the other.\n\n\u003e Note that the **LicenseManager_12noon.Client** NuGet package includes the fixes in the\n[Standard.Licensing.12noon NuGet package](https://nuget.org/packages/Standard.Licensing.12noon)\nfor the `Expiration` property.\nWhen/If [the pull request with those fixes](https://github.com/junian/Standard.Licensing/pull/47)\nis accepted into the original **Standard.Licensing** project,\nthe **Standard.Licensing.12noon** package will be deprecated.\n\nYou can download the License Manager X application from the Microsoft Store.\n\n\u003ca href=\"https://apps.microsoft.com/store/detail/9PFBGG44SHLM?launch=true\u0026mode=full\"\u003e\n\t\u003cimg width=\"300\" src=\"https://get.microsoft.com/images/en-us%20dark.svg\"/\u003e\n\u003c/a\u003e\n\n![License Manager X](https://raw.githubusercontent.com/12noonLLC/LicenseManagerX/master/LicenseManagerX.png)\n\n## Features\n\n### Key Management\n\n| Property | Usage |\n|----------|-------|\n| Passphrase | Secret used to generate public/private keypair and to create a license |\n| Public key | Used by the licensed application to validate the license |\n| ID | License ID (You can use it any way you want or not at all) |\n| Product ID | Used by the licensed application to verify the executable and public key. |\n| Lock to assembly | This ensures the license is associated _ONLY_ with _THIS_ build of the licensed application. |\n\nThe application maintains the private key in the `.private` file but does not display it.\n\n### Product\n\n| Property | Usage |\n|----------|-------|\n| Name | The product name |\n| Version | The product version |\n| Date published | The date the product was published |\n\nThese values can be displayed by the licensed application.\n\nThe publish date can represent any date you want.\n\n### Product Features\n\nYou can add custom product features to your license by specifying them in the `key=value` format.\nThese features allow you to define additional metadata or functionality for your product.\n\n1. In the **Product features** field, enter your custom feature in the `key=value` format.\n2. Add as many features as needed, each on a new line.\n3. Save the license file to apply the changes.\n\nFor example:\n\n| Key=Value       |\n|-----------------|\n| Feature1=Enabled |\n| Feature2=False |\n| MaxWidgets=100 |\n\nThe licensed application can then read and use these features as needed.\n\n### License\n\n| Property | Usage |\n|----------|-------|\n| Type | Standard or trial license |\n| Expiration Date | The date on which the license expires (no time, no time zone info). `DateOnly.MaxValue` means no expiry. |\n| Expiration Days | The number of days until the license expires. Zero means no expiry. |\n| Quantity | Minimum value is one (1) |\n\nThe licensed application can check the type to permit only certain features.\n\nThe license expires at 12:00 AM (midnight) local time on the specified date. Stored as a time-zone-agnostic date.\n\nIf the expiration days is set to zero, there is no expiry.\n\nThe quantity is not enforced.\n\n#### Expiration Date Semantics\n\n**Important:** Expiration dates are stored and compared using local time, not UTC:\n\n- **Storage:** The expiration date is stored as a `DateOnly` value in ISO 8601 format (`yyyy-MM-dd` in XML files).\n- **Interpretation:** An expiration date of April 12 means the license expires at 12:00 AM (midnight) **local time** on April 12.\n- **Validation:** When validating a license, the current local date is compared against the expiration date.\n- **Example:** If a license is set to expire on April 12 and the current local time is April 11 at 11:59 PM, the license is still valid. Once the local clock strikes 12:00 AM on April 12, the license is expired.\n\nThis approach ensures consistent expiration behavior across different time zones without requiring time zone conversion logic.\n\n#### Serialization Format\n\n- **New Format:** Expiration dates are saved in ISO 8601 format: `2027-12-01` (yyyy-MM-dd)\n- **Backwards Compatibility:** The system can read expiration dates in the following legacy formats in `.private` files:\n  - Old DateTime string: `12/01/2027 00:00:00`\n  - RFC1123 format: `Sun, 02 Jan 2028 00:00:00 GMT`\n  - Any other culture-invariant DateTime format\n  \nWhen loading an older `.private` file with legacy date formats, the expiration date is automatically converted to the new ISO 8601 format when the keypair is next saved.\n\n### License Attributes\n\nLicense attributes can also be added using the `key=value` format.\nThese attributes allow you to define additional properties for the license.\n\n1. In the **License attributes** field, enter your custom attribute in the `key=value` format.\n2. Add as many attributes as needed, each on a new line.\n3. Save the license file to apply the changes.\n\nFor example:\n\n| Key=Value       |\n|-----------------|\n| Region=US |\n| SupportLevel=Premium |\n\nThe licensed application can access these attributes to enforce specific behaviors or display relevant information.\n\n### Licensee\n\nThis information can be displayed by the licensed application.\n\n| Property | Usage |\n|----------|-------|\n| Name | Name of the licensee |\n| Email | Email of the licensee |\n| Company | Company of the licensee (optional) |\n\n## Usage\n\n### Create a New License\n\nNote that the public key and product ID are passed by the licensed application\nto validate the license, so you only want to create a new keypair or change the\nproduct ID if you want to change them in the licensed application, rebuild it,\nand create new licenses for anyone who will use the new build.\n\n1. Create a keypair by entering a value for _Passphrase_ and pressing _Create Keypair_ button.\n1. Enter a _Product ID_.\n1. Optionally, lock the license to a specific build of the licensed application. Technically, this\ncould be _any_ file, but one that is unique to a specific build (e.g., an EXE or DLL) is most useful.\n1. Fill in the product information, license information, and licensee information.\n1. Press the _Save Keypair..._ button. This will prompt you for where to save the `.private` file.\n1. Press the _Save License..._ button. This will prompt you for where to save the `.lic` file.\n\nThe `.private` file contains all of the information used to create the license, including the secrets.\nDo keep the `.private` file somewhere safe.\nDo NOT add the `.private` file to source control.\nYou will need it to create more licenses for your licensed application\n(unless you want to update the application to use a new public key).\n\nThe only intentional exception in this repository is the example `.private` file under `LicenseManagerX_Example`,\nwhich exists only so users can inspect a sample end-to-end setup.\n\n### Create a License Based on an Existing License\n\n1. Press the *Load Keypair or License or Both...* button to select a `.private` or\n`.lic` file (or both of them). Alternatively, you can drag/drop a `.private` and/or `.lic` file.\n1. After loading both files, License Manager X will validate the license file.\n\nIf the license is invalid (_e.g._, it expired or the assembly has changed), you can create a new (valid) license.\n\n1. Now you can update the product, license, or licensee information as needed.\n1. Press the _Save Keypair..._ button to save the keypair file. This will\nprompt you for where to save the `.private` file.\n1. Press the _Save License..._ button to create a new license. This will\nprompt you for where to save the `.lic` file.\n\n### Command Line Interface\n\nThe License Manager X application includes a built-in command line interface. The same executable\ncan run in both GUI mode (when launched without arguments) and CLI mode (when arguments are provided).\n\nOnce you have created a `.private` file using the GUI, you can use the\ncommand line interface to generate new license files more efficiently.\n\n#### Usage\n\n`lmx` is the Windows app execution alias for License Manager X. You can manage this in Windows Settings.\n\n```cmd\nlmx --private \u003cpath\u003e [--save] [--license \u003cpath\u003e] [options]\n```\n\n#### Required Arguments\n\n- `--private, -p \u003cpath\u003e` - Path to the `.private` file\n\n#### Display Keypair, Save Keypair, or Create License\n\nYou can specify one or more of these switches.\nIf you do not specify any of these, the CLI only displays the properties from the keypair file.\n\n- `--license, -l \u003cpath\u003e` - Create a new `.lic` file (will not overwrite unless `--force` is used)\n- `--save, -s` - Write the specified values to the `.private` file\n\n#### Optional Arguments\n\n- `--help, -h` - Show help\n- `--force, -f` - Overwrite the license file if it already exists\n- `--product-version, -v \u003cversion\u003e` - Product version\n- `--product-publish-date, -pd \u003cdate\u003e` - Product publish date (YYYY-MM-DD format)\n- `--product-features, -pf \u003cpairs\u003e` - Product features as key=value pairs\n- `--type, -t \u003cStandard | Trial\u003e` - License type\n- `--quantity, -q \u003cnumber\u003e` - License quantity (positive integer)\n- `--expiration-days, -dy \u003cdays\u003e` - Expiration in days (0 = no expiry)\n- `--expiration-date, -dt \u003cdate\u003e` - Expiration date (YYYY-MM-DD format)\n- `--license-attributes, -la \u003cpairs\u003e` - License attributes as key=value pairs\n- `--lock \u003cpath\u003e` - Lock license to a specific file (_e.g.,_ EXE or DLL)\n\n#### Examples\n\n```cmd\nREM Display properties from .private file\nlmx -p my.private\n\nREM Create a standard license using default settings from .private file\nlmx -p my.private -l customer.lic\n\nREM Create a 30-day trial license\nlmx -p my.private -l trial.lic --type Trial --expiration-days 30\n\nREM Create an enterprise license with custom quantity and version\nlmx -p my.private -l enterprise.lic --quantity 100 --product-version 2.1.0\n\nREM Create a license locked to a specific executable\nlmx -p my.private -l locked.lic --lock C:\\MyApp\\MyApp.exe\n\nREM Create a license with custom product features\nlmx -p my.private -l featured.lic --product-features \"Color=Blue Bird=Heron MaxUsers=50\"\n\nREM Create a license with custom attributes\nlmx -p my.private -l attributed.lic --license-attributes \"Department=Engineering Location=Seattle\"\n\nREM Combine multiple options\nlmx -p my.private -l full.lic --type Trial --expiration-days 30 --lock C:\\MyApp\\MyApp.exe --product-features \"Edition=Pro\" --license-attributes \"CustomerTier=Gold\"\n```\n\n#### Key=Value Format\n\nFor `--product-features` and `--license-attributes`, use space-separated key=value pairs:\n- Format: `\"key1=value1 key2=value2 key3=value3\"`\n- Keys cannot be empty\n- Values can be empty: `\"Key=\"` or `Key`\n- Spaces in values are not supported (use quotes around individual pairs if needed)\n\n#### Security Notes\n\nThe CLI **cannot** override these protected properties from the `.private` file:\n- Passphrase\n- Public or private keys  \n- Product name\n- Customer name, email, or company\n\n**Reserved Names:**\n- Product features cannot use: `Product`, `Version`, `Publish Date`\n- License attributes cannot use: `Product Identity`, `Assembly Identity`, `Expiration Days`\n\nIf the license file already exists, it will not be overwritten and an error will be displayed.\n\n### The Licensed Application\n\nInstall the `LicenseManager_12noon.Client` NuGet package in your application.\n\nThe licensed application must pass the **Product ID** and the **Public Key** to the license validation API.\n\n```\nconst string PRODUCT_ID = \"My Product ID\";\t// Copied from the License Manager X application\nconst string PUBLIC_KEY = \"The Public Key\";\t// Copied from the License Manager X application\nLicenseFile license = new();\nbool isValid = license.IsLicenseValid(PRODUCT_ID, PUBLIC_KEY, out string messages);\nif (!isValid)\n{\n\t// INVALID\n\tMessageBox.Show(\"The license is invalid. \" + messages);\n\treturn;\n}\n\n// VALID\nif (license.StandardOrTrial == LicenseType.Trial)\n{\n\t// Example: LIMIT FEATURES FOR TRIAL\n}\n```\n\nIf the license is valid, you can use any of the properties (_e.g._, for display or to limit features).\n\nAlternatively, you can use the `Standard.Licensing` NuGet package to validate the license in your application.\n\n**Note:** Of course, the hash of _Product ID_ and _Public Key_ will not prevent a determined\nhacker from working around the license. However, it will prevent a simple text substitution\nof the public key.\n\nYou could also do something more involved, such as prompting the licensee the first\ntime they run the application to enter some secret text (_e.g._, a password or GUID)\nand storing a hash of it and the public key in protected storage.\nThen the application could use the hash as the _Product ID_.\nOf course, the licensee would have to keep that text as secret as they\nshould keep the license file.\n\n### Example Application\n\nThe **LicenseManagerX_Example** project is an example application to demonstrate how to\nuse the NuGet client library to validate a license and access the license's information.\n\n**Note:** The `.lic` (license) files are managed by the Standard.Licensing library and are not\ndirectly parsed or modified by License Manager X.\nExpiration dates in `.lic` files use UTC format as defined by the Standard.Licensing library.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F12noonllc%2Flicensemanagerx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F12noonllc%2Flicensemanagerx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F12noonllc%2Flicensemanagerx/lists"}