{"id":22271170,"url":"https://github.com/cryptolens/cryptolens-cpp","last_synced_at":"2025-07-28T13:32:36.597Z","repository":{"id":43106846,"uuid":"86050928","full_name":"Cryptolens/cryptolens-cpp","owner":"Cryptolens","description":"C++ Interface for Cryptolens Web API","archived":false,"fork":false,"pushed_at":"2023-08-26T08:06:20.000Z","size":920,"stargazers_count":21,"open_issues_count":1,"forks_count":12,"subscribers_count":4,"default_branch":"master","last_synced_at":"2023-08-26T08:26:20.299Z","etag":null,"topics":["license-checking","licensing-as-a-service","licensing-library"],"latest_commit_sha":null,"homepage":"https://cryptolens.io/support-cycle/","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Cryptolens.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-03-24T09:32:51.000Z","updated_at":"2023-08-11T03:31:52.000Z","dependencies_parsed_at":"2023-02-04T06:46:39.954Z","dependency_job_id":null,"html_url":"https://github.com/Cryptolens/cryptolens-cpp","commit_stats":null,"previous_names":[],"tags_count":5,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cryptolens%2Fcryptolens-cpp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cryptolens%2Fcryptolens-cpp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cryptolens%2Fcryptolens-cpp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cryptolens%2Fcryptolens-cpp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Cryptolens","download_url":"https://codeload.github.com/Cryptolens/cryptolens-cpp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227914220,"owners_count":17839245,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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-checking","licensing-as-a-service","licensing-library"],"created_at":"2024-12-03T12:10:54.741Z","updated_at":"2024-12-03T12:10:59.815Z","avatar_url":"https://github.com/Cryptolens.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Cryptolens Client API for C++\n\nOn this page, we have outlined several examples of how to get started with the Cryptolens Client API for C++.\n\n\u003e **Note**, Cryptolens Client API for C++ currently supports a subset of the full Cryptolens Web API. Please contact us if you need something in particular.\n\nYou can find the API documentation here: [https://help.cryptolens.io/api/cpp/](https://help.cryptolens.io/api/cpp/).\n\nIf you are already familiar with the .NET version of the library, we have summarized key differences in an [announcement](https://cryptolens.io/2017/08/new-client-api-for-c/) on our blog.\n\n\n## Table of contents\n\n* [Example projects](#example-projects)\n  - [CMake](#cmake) (for Linux)\n  - [Visual Studio](#visual-studio) (for Windows)\n* [Library overview](#library-overview)\n* [Error handling](#error-handling)\n* [Offline activation](#offline-activation)\n* [HTTPS requests outside the library](#https-requests-outside-the-library)\n\n\n## Example projects\n\n[This repository](https://github.com/Cryptolens/cryptolens-cpp) contains some example projects using the library in the examples/ directory.\nThe cmake example project is set up to be compiled against OpenSSL and libcurl, while the\nVisualStudio project builds against the CryptoAPI and WinHTTP libraries available on Windows.\nThe rest of this section contains instructions for how to build the example projects.\n\n### CMake\n\nFirst we need to install libcurl and OpenSSL, including the header files, unless that has\nalready been done.\n\n```\nDebian/Ubuntu:\n$ apt-get install libcurl4-openssl-dev libssl-dev\nFedora/Red Hat:\n$ yum install libcurl-devel openssl-devel\n```\n\nNext, clone the repository and build the examples\n\n```\n$ git clone https://github.com/Cryptolens/cryptolens-cpp.git\n$ cd cryptolens-cpp/examples/unix/cmake\n$ mkdir build\n$ cd build\n$ cmake ..\n$ make -j8\n$ ./example_activate\n```\n\n### Visual Studio\n\nGetting started with the example project for Visual Studio requires two steps. First we\nbuild the library file the example project will statically link against, then we build\nthe example project.\n\nThe following steps build the library:\n\n * Open the solution file *vsprojects/Cryptolens.sln* in Visual Studio.\n * Set platform and configuration as appropriate, e.g. *x64* and *Debug*\n * Build the project in Visual Studio\n * Now the folder *vsprojects/Output/$Platform/$Configuration/* contains the *Cryptolens.lib* file. With platform set to \"x64\" and configuration set to \"Debug\", the file is *vsprojects/Output/x64/Debug/Cryptolens.lib*\n\nNow we can build the example project:\n\n * Open *examples/VisualStudio/VisualStudio.sln*\n * Set configuration and platform in the same way as when building the library\n * Build and run the project.\n\nInstructions for how to add the library to your own Visual Studio project can be found [here](/tutorials/add-to-project-windows.md).\n\n## Library overview\n\nThis section contains an overview of the standard way to implement the library in an\napplication. The first step is to include the appropriate headers:\n\n```cpp\n#include \u003ccryptolens/core.hpp\u003e\n#include \u003ccryptolens/Error.hpp\u003e\n#include \u003ccryptolens/Configuration_XXX.hpp\u003e\n#include \u003ccryptolens/MachineCodeComputer_YYY.hpp\u003e\n\nnamespace cryptolens = ::cryptolens_io::v20190401;\n```\n\nBesides including headers the above code sets up a namespace alias for the api version of the C++\nlibrary we are using.\n\nThe `Configuration` class allows for using different libraries for parsing JSON, making HTTPS\nrequests, performing cryptographic operations as well as minor changes in the behaviour of the\nlibrary. We currently support the following `Configurations` and `MachineCodeComputers`:\n\n| Configuration                         | Description                                           |\n| -----------------------------------   | ----------------------------------------------------- |\n| `Configuration_Unix`                 | Good default configuration for Unix-like based systems. Uses ArduinoJson 5, libcurl and OpenSSL. Checks if the license key has expired against the users system time. |\n| `Configuration_Unix_IgnoreExpires`   | Same as `Configuration_Unix`, but does not check if the license key has expired against the users system time. |\n| `Configuration_Windows`               | Good default configuration for Windows based systems. Uses ArduinoJson 5, WinHTTP and CryptoAPI. Checks if the license key has expired against the users system time. |\n| `Configuration_Windows_IgnoreExpires` | Same as `Configuration_Windows`, but does not check if the license key has expired against the users system time. |\n\n| MachineCodeComputer             | Description                                     |\n| ------------------------------- | ----------------------------------------------- |\n| `MachineCodeComputer_COM` | Works on Windows and computes a machine code using functionallity provided through COM. |\n| `MachineCodeComputer_static` | Does not automatically compute a machine code, instead the machine code is set by calling `set_machine_code()`. |\n| `MachineCodeComputer_SystemdDBusInodes_SHA256` | Works on Linux systems and computes a machine code based on information provided by Systemd, DBus and the filesystem. |\n\nThe next step is to create and set up a handle class responsible for making requests\nto the Cryptolens Web API.\n\n```cpp\nusing Cryptolens = cryptolens::basic_Cryptolens\n                     \u003ccryptolens::Configuration_XXX\u003ccryptolens::MachineCodeComputer_static\u003e\u003e;\n\ncryptolens::Error e;\nCryptolens cryptolens_handle(e);\n\ncryptolens_handle.signature_verifier.set_modulus_base64(e, \"ABCDEFGHI1234\");\ncryptolens_handle.signature_verifier.set_exponent_base64(e, \"ABCD\");\n\n// This line is only for MachineCodeComputer_static and sets the machine code to a static value\ncryptolens_handle.machine_code_computer.set_machine_code(e, \"289jf2afs3\");\n```\n\nHere the strings `\"ABCDEFGHI1234\"` and `\"ABCD\"` needs to be replaced by your public keys. These\ncan be found when logged in on Cryptolens.io from the menu in the top-right corner\n(\"Hello \u003cusername\u003e!\") and then *Security Settings*. The example above corresponds to\nthe following value on the website\n\n```\n\u003cRSAKeyValue\u003e\u003cModulus\u003eABCDEFGHI1234\u003c/Modulus\u003e\u003cExponent\u003eABCD\u003c/Exponent\u003e\u003c/RSAKeyValue\u003e\n```\n\nIn this example we set the machine code used to `\"289jf2afs3\"`.\n\nNow that the handle class has been set up, we can attempt to activate a license key\n\n```cpp\ncryptolens::optional\u003ccryptolens::LicenseKey\u003e license_key =\n  cryptolens_handle.activate\n    ( // Object used for reporting if an error occured\n      e\n    , // Cryptolens Access Token\n      \"WyI0NjUiLCJBWTBGTlQwZm9WV0FyVnZzMEV1Mm9LOHJmRDZ1SjF0Vk52WTU0VzB2Il0=\"\n    , // Product id\n      3646\n    , // License Key\n      \"MPDWY-PQAOW-FKSCH-SGAAU\"\n    );\n\nif (e) {\n  // An error occured. Handle it.\n  handle_error(e);\n  return 1;\n}\n```\n\nThe `activate` method takes several arguments:\n\n 1. The first argument is used to indicate if an error occured, and if so can provide additional\n    information. For more details see the section *Error handling* below.\n 1. We need an access token with the `Activate` scope. Access tokens can be created at\n    https://app.cryptolens.io/User/AccessToken/.\n 1. The third argument is the product id, this can be found at the page for the corresponding product at\n    https://app.cryptolens.io/Product.\n 1. The fourth argument is a string containing the license key string, in most cases this will be\n    input by the user of the application in some application dependent fashion.\n\nAfter the `activate` call we check if an error occurred by converting `e` to bool. If an error\noccured this returns true. If an error occurs, the optional containing the `LicenseKey` object\nwill be empty, and dereferencing it will result in undefined behaviour.\n\nIf no error occurs we can inspect the `LicenseKey` object for information as follows\n\n```cpp\nstd::cout \u003c\u003c \"License key for product with id: \" \u003c\u003c license_key-\u003eget_product_id() \u003c\u003c std::endl;\n\nif (license_key-\u003echeck()-\u003ehas_expired(1234567)) {\n  std::cout \u003c\u003c \"Your subscription has expired.\" \u003c\u003c std::endl;\n  return 1;\n}\n\nif (license_key-\u003echeck()-\u003ehas_feature(1)) { std::cout \u003c\u003c \"Welcome! Pro version enabled!\" \u003c\u003c std::endl; }\nelse                                      { std::cout \u003c\u003c \"Welcome!\" \u003c\u003c std::endl; }\n```\n\n\n## Error handling\n\nThis section describes in more detail how the library reports when something went wrong.\nThe library uses an exceptionless design and return values use optionals where they can be missing.\nAll functions accept as the first argument a reference to `cryptolens::basic_Error` which\nis used to indicate when an error has occured as well as for reporting more detailed error information.\n\nFurthermore, if an error occurs, subsequent calls to the library with that error object as first\nargument are turned into noops. consider the following code:\n\n```cpp\ncryptolens::Error e;\nf1(e);\nf2(e);\n```\n\nIf an error occurs during the call to `f1()`, `f2()` will not be performed. This allows writing\nseveral function calls after each other without having to check for errors after\nevery single call.\n\n\n## Offline activation\n\nOne way to support activation while offline is to initially make one activation request\nwhile connected to the internet and then saving this response. By then reading the saved\nresponse and performing the cryptographic checks it is not necessary to make another\nrequest to the Web API in the future. Thus we can proceed as during online activation\nbut save the response as a string:\n\n```cpp\ncryptolens::Error e;\nCryptolens cryptolens_handle(e);\n\ncryptolens_handle.signature_verifier.set_modulus_base64(e, \"ABCDEFGHI1234\");\ncryptolens_handle.signature_verifier.set_exponent_base64(e, \"ABCD\");\n\ncryptolens_handle.machine_code_computer.set_machine_code(e, \"289jf2afs3\");\n\ncryptolens::optional\u003ccryptolens::LicenseKey\u003e license_key =\n  cryptolens_handle.activate\n    ( // Object used for reporting if an error occured\n      e\n    , // Cryptolens Access Token\n      \"WyI0NjUiLCJBWTBGTlQwZm9WV0FyVnZzMEV1Mm9LOHJmRDZ1SjF0Vk52WTU0VzB2Il0=\"\n    , // Product id\n      3646\n    , // License Key\n      \"MPDWY-PQAOW-FKSCH-SGAAU\"\n    );\nif (e) { handle_error(e); return 1; }\n\nstd::string s = license_key-\u003eto_string();\n```\n\nThe string *s* can now be saved to a file or similar, in an application dependent manner. In order\nto check the license later when offline, load the string *s* and recover the license key as follows:\n\n```cpp\ncryptolens::Error e;\nCryptolens cryptolens_handle(e);\n\ncryptolens_handle.signature_verifier.set_modulus_base64(e, \"ABCDEFGHI1234\");\ncryptolens_handle.signature_verifier.set_exponent_base64(e, \"ABCD\");\n\ncryptolens_handle.machine_code_computer.set_machine_code(e, \"289jf2afs3\");\n\ncryptolens::optional\u003ccryptolens::LicenseKey\u003e license_key =\n  cryptolens_handle.make_license_key(e, s);\nif (e) { handle_error(e); return 1; }\n```\n\nA full working version of the code above can be found as *example_offline.cpp* among the examples.\n\n## HTTPS requests outside the library\n\nIn some cases it may be needlessly complex to have the Cryptolens library be responsible\nfor initiating the HTTPS request to the Web API, instead it might be easier to have some\nother part of the application that does the HTTPS request, and then only use this library\nfor making sure that the cryptographic signatures are valid. This can be accomplished\nby using the `handle_activate()` function as follows\n\n```cpp\nstd::string web_api_response; // Some other part of the code creates and populates this object\n\ncryptolens::Error e;\nCryptolens cryptolens_handle(e);\n\ncryptolens_handle.signature_verifier.set_modulus_base64(e, \"ABCDEFGHI1234\");\ncryptolens_handle.signature_verifier.set_exponent_base64(e, \"ABCD\");\n\ncryptolens_handle.machine_code_computer.set_machine_code(e, \"289jf2afs3\");\n\ncryptolens::optional\u003ccryptolens::LicenseKey\u003e license_key =\n  cryptolens_handle.make_license_key(e, web_api_response);\nif (e) { handle_error(e); return 1; }\n```\n\nThis code is also applicable to the case where one wants a completly air-gapped offline activation.\nIn this case the `web_api_response` string would be prepared and delivered one for example an USB\nthumb drive, and the application then reads this response from the device and stores it in\nthe `web_api_response` string.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcryptolens%2Fcryptolens-cpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcryptolens%2Fcryptolens-cpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcryptolens%2Fcryptolens-cpp/lists"}