C/C++ ISV Application Development Guide
Overview Of License Enabling Activities
Defining Your License Management Policies
Example Of Single-User License Key Check
Example Of Server License Key Check
Example Of License Key Check With Customization For OEM Key
Coding Against The Extended API
Enabling Deferred-mode Licensing With The Extended API
Checking Access Controlled Keys
Coding For Automatic License State Management
Using Digital Signatures For Anti-Spoofing
This document guides you through the specifics of the process of license-enabling your C/C++ product with EasyLicenser. It adds detail to the overview of the EasyLicenser C/C++ Run Time Library API that is presented in the EasyLicenser Concepts guide.
The activities encompass:
A key decision
you need to make at the onset is whether you wish to enforce locking your
license keys to specific hardware and / or operating system. Although locking
your key provides a high degree of protection, it is also a sales inhibitor,
as it subjects your end-customer to onerous procedures both at the time you
take their order and whenever customers want to relocate their product installation.
The approach is also less portable across platforms. The next decision you
need to make is what you want to lock your key to: proprietary hardware,
or the logical operating system runtime environment. If the former, you will
need to implement or obtain hardware and operating system specific code and
plug it into the EasyLicenser runtime framework. If the latter, you can utilize
EasyLicenser's built-in enforcement facilities.
If you are going to node-lock your license keys, another decision you
need to make is the tradeoff between convenience and security: whether
security requirements override convenience, or whether a short time window
of vulnerability is acceptable for the purpose of eliminating the process
of explicitly acquiring node lock information from the customer.
When your product is licensed for time limited or metered use, you can decide on what you want to have happen when a license key check indicates an expiring or expired key. You can define thresholds for generating warnings on expiring keys and grace periods or quotas to suppress generating errors when a quota or expiration date is exceeded. For time limited licenses, you will also need to decide whether the licenses are to be individually issued and tracked, or whether a single relative-time-limited license is to be included with the product distribution for convenience. For metered licenses, you will also need to decide whether to let the EasyLicenser runtime automatically manage metered state.
When your product is licensed according to paid-for options and features, you will accordingly define product options in your license key generation environment, and process the option values in your application.
EasyLicenser has built-in license management models, types and parameters. If you have a specialized need for your own variation to the built-in policies, you can accomplish this by defining your own custom handler.
The specific mechanics of accomplishing these tasks are described below.
The EasyLicenser runtime library provides two levels of API's:
Both API's are threadsafe.
Four API calls are provided in ezLicenseInfo.h for checking a license key:
All core API calls are available with
three signatures: a standard API call that is backward compatible with all previous versions
of EasyLicenser, an access-control API, new in EasyLicenser 2.0, that accepts
two additional parameters: a product name and an application password public key
that is backward compatible with EasyLicenser 2.0, and a strict access-control API that
accepts a "strict" parameter, which is implicitly false for the older signature for
backward compatibility.
The access control API is required to be used with access-controlled keys and will
also work with keys that are not based on products having application passwords
defined for them. The sole purpose of the standard API call signature is backward
compatibility. For all new application development, the access control API signature
is recommended. The access control API with strict password check should be used for
all new application development, for security.
If your application does not require customized or highly secure license management, you can use either of the first two API’s according to whether your product is a user or server product. Otherwise, you will find it convenient to use one of the functionally complete APIs.
Three key API calls are available with the ezLicenseExtAPI.h header file for managing the lifecycle of a license key at an application installation:
The API is an access-control API, and application password checking is implicitly strict.
All application categories can use the extended API. That is, it is not a requirement that the application require deferred time limited licensing, deferred node locking or automatic metering.
The specific details of the API
are available in the form of in-context comments in the ezLicenseInfo.h C/C++ header file
located at the cpp/include directory. Some simple examples will be
illustrated below that show how the API calls are used in typical application
scenarios. Source and binary code
for additional examples are available in the cpp/demo directory.
In particular,
the C_Demo.c application is a simple Hello World
application that performs a simple check on a license key provided as an
input parameter based on a specified user / host name. For details on the
demo program
and how to run it, see the description of the directory structure in the Setup,
Management And Deployment Guide. The cdemosecure.cpp application
is similar to C_Demo.c, but illustrates the use of the secure
API. Use of the secure API for automatic state management is illustrated with
the cdemostate.c application.
Suppose you have a desktop application such as a file management utility program that you sell to end consumers.
In your environment, you create a product definition for your product, which you call FileManagerProduct and with which you associate a secret password MySecret. The License Manager displays a corresponding application password public key rTxWsuxjr4/s3J=. Your application developer embeds the public key into your application and uses the product name and public key at the time of a license key check, as illustrated below.
Whenever a new customer visits your web site and downloads your application and pays by credit card for a perpetual license to use it, your web site defines a serial number or user id, which is also used as the EasyLicenser user name input to a key your web site programmatically generates and emails to your customer. The key that you generate is a User license model, of User license type. It is not time limited and does not have a quota limit defined on it.
At product installation time, your product asks the user for the key, which is then stored in the operating system registry. Subsequently, each time the user runs your product, it prompts your user for the user id authentication information. Your code can take that user name input, retrieve the license key from the registry, and perform the license key check as follows:
// includes
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <ezLicenseInfo.h>
:
// Get the user name with the appropriate UI widget:
char *username = uiWidget->getText();
// Check the license key that is already obtained from the registry into a "config" class.
// (note: "config" is not part of EasyLicenser)
// First, allocate a license info context
void * ezLicInstance = allocLicenseInfo();
int errorCode =
checkSingleUserLicenseKeyBasic(
ezLicInstance,
config->getLicenseKey(),
0, // no grace period for expired keys
0, // not metered license: no quota used to date
0, // metered-license quota threshold N/A
0, // no grace period for expired keys
0, // not metered license: no quota grace
username, // user name matching what’s in the key
"FileManagerProduct", // product name matching what’s in the key
"rTxWsuxjr4/s3J=" // application password public key
);
// errorCode is 0 if success, > 0 if success-with-warning,
// < 0 if error. Analyze it for specifics.
if (errorCode >= 0) {
// Extract some interesting license params if needed
char *customCookie = getCustomCookie(ezLicInstance);
// analyze custom cookie in application-specific way
analyzeCustomCookie(customCookie);
// Check for warning conditions eg. about-to-expire key
checkWarnings(errorCode);
} else
// check for error codes defined in ezlicStatusCodes.h
checkErrors(errorCode);
// Free license key context
freeLicenseInfo(ezLicInstance);
Suppose you have an application server product Clogix having an application password public key ZrTxWs0xjr4/s3== that you wish to license by the number of concurrent sessions on the application server. You wish to lock the user into a specific host machine, therefore you adopt an enforced host naming policy that requires your customer to provide you with the DNS host name for their server machine at the time of accepting an order and generating a key.
The key that you generate is of a Server license model, and Concurrent User license type. At the time of generating the key, you specify an upper limit on the number of concurrent users according to what your customer paid for. It is not time limited, and you do not define a quota limit on it. The host name that you specify is based on what your customer tells you. Your customer obtains this information through a "uname -a" shell command on the server machine targeted for deployment of your application.
Your server application is designed to load at startup time an application property text file that includes, among other items, the license key and the host name, similar to the following:
:
LicenseKey=tFy67+h=…
HostName=licensedHostName1
At run time, either periodically or in response to specific events such as session initiation, your product code can interrogate its environment to obtain the number of active sessions and the application properties and check the license:
// includes
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <ezLicenseInfo.h>
:
// First, get the host name and license key,
// and the active sessionCount
char *hostName = AppProperty.getProperty("HostName");
char *licenseKey = AppProperty.getProperty("LicenseKey");
long sessionCount =
App.getActiveSessionCount(); // the current value
// Check the license key
// First, allocate a license info context
void * ezLicInstance = allocLicenseInfo();
int errorCode =
checkMultiUserLicenseKeyBasic(
ezLicInstance,
licenseKey,
0, // no grace period for expired keys
0, // not metered license: no quota used to date
0, // metered-license quota threshold N/A
0, // no grace period for expired keys
0, // not metered license: no quota grace
hostName, // host name matching what’s in the key
sessionCount, // current usage value
"Clogix", // product name matching key
"rTxWsuxjr4/s3J=" // application password public key
);
// errorCode is 0 if success, > 0 if success-with-warning,
// < 0 if error. Analyze it for specifics.
if (errorCode >= 0) {
// Extract some interesting license params if needed
char *customCookie = getCustomCookie(ezLicInstance);
// analyze custom cookie in application-specific way
analyzeCustomCookie(customCookie);
// Check for warning conditions eg. about-to-expire key
checkWarnings(errorCode);
} else
// check for error codes defined in ezlicStatusCodes.h
checkErrors(errorCode);
// Free license key context
freeLicenseInfo(ezLicInstance);
Suppose you are an OEM reseller and your desktop product embeds infrastructure GUI technology obtained from an OEM. Your OEM would like to ensure that their embedded product can only be used in the context of your product. It should not be possible for your customer to decompose your product to extract the OEM’s product and make unlicensed use of the latter. At the same time, you do not wish to impose an additional license management burden on your customer – you wish to distribute a single key to your customer.
Your OEM can provide you with
their key, which may or may not be based on EasyLicenser. At the time
of key composition, you can go to the Custom tab and provide the OEM key value
in the Custom Key text area as follows:
tFyU6h7G….
Your application code that checks for the license key will include a custom key handler that recursively performs a license check against the custom key (in this example, we are assuming the key is access controlled as well):
// includes
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <ezLicenseInfo.h>
// custom key handler for OEM key processing: fwd reference
// Signature conforms to that specified in <ezLicCustomKeyHandler.h>
int OemKeyHandler(void *keyCtx, const char *customKey);
:
// Get the user name with the appropriate UI widget:
char *username = uiWidget->getText();
// Check the license key that is already obtained from the registry into a "config" class.
// (note: "config" is not part of EasyLicenser)
// First, allocate a license info context
void * ezLicInstance = allocLicenseInfo();
int errorCode =
checkLicenseKey(
ezLicInstance,
config->getLicenseKey(),
OemKeyHandler, // custom key handler for processing OEM key
"WidgetMaker", // OEM username passed in as application ctx
0, // no grace period for expired keys
0, // not metered license: no quota used to date
0, // metered-license quota threshold N/A
0, // no grace period for expired keys
0, // not metered license: no quota grace
username, // user name matching what’s in the key
"FileManagerProduct", // product name matching what’s in the key
"rTxWsuxjr4/s3J=" // application password public key
);
// errorCode is 0 if success, > 0 if success-with-warning,
// < 0 if error. Analyze it for specifics.
if (errorCode >= 0) {
// Success
// Check for warning conditions eg. about-to-expire key
checkWarnings(errorCode);
} else
// check for error codes defined in ezlicStatusCodes.h
checkErrors(errorCode);
// Free license key context
freeLicenseInfo(ezLicInstance);
:
// Custom key handler for OEM key processing
int OemKeyHandler(void *appCtx, const char *customKey) {
// First, allocate a license info context
void * ezLicInstance = allocLicenseInfo();
int errorCode =
checkLicenseKey(
ezLicInstance,
customKey, // custom key is the OEM key
NULL, // no custom key handler for OEM key itself
NULL, // no app ctx
0, // no grace period for expired keys
0, // not metered license: no quota used to date
0, // metered-license quota threshold N/A
0, // no grace period for expired keys
0, // not metered license: no quota grace
(char *)appCtx, // user name matching what’s in the key
"Widget", // product name matching what’s in the OEM key
"TwRxWquZjr43x=" // application password public key
);
// Free license key context
freeLicenseInfo(ezLicInstance);
return errorCode;
}
The above approach can be extended to any number of embedded OEM keys, possibly in combination with other customizations. To accomplish this, simply provide a list of name-value pairs instead of a single key value and process the entire list.
The specific details of the API
are available in the form of in-context comments in the ezLicenseExtAPI.h C/C++ header file
located at cpp/include directory. The API is used in essentially
the same manner regardless of the license policy that is encoded in the keys,
with the difference that an additional auxiliary key license key
parameter, corresponding to an enabler key provided by Agilis, is supplied
in order to enable deferred-time-limited or deferred-node-locked
licensing functionality. If deferred-licensing functionality is not required
(for example, corresponding to the scenario where a trial license is upgraded to
a production license), a null value is provided for the auxiliary key at the time
of activation.
To activate a license for a desktop application installation that is currently not in an activated
state, your application's activation logic will invoke the activateExtAPILicense
API call (using the same example as the single-user license above), as follows:
// includes
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <ezLicenseInfo.h>
#include <ezLicenseExtAPI.h>
:
// Activate the license key provided by you to your end customer,
// optionally enabled for deferred-mode licensing with an auxiliary key provided by Agilis.
void *licenseInfo = NULL;
int status =
activateExtAPILicense(
config->getLicenseKey(), auxKey, NULL, NULL, userName,
"FileManagerProduct", "rTxWsuxjr4/s3J=",
NULL, NULL, TRUE, auxKey != NULL,
&licenseInfo);
// deferred node locking only if auxiliary key is specified.
if (status < 0) { // error
:
:
} else {
// extract and save key cookie in persistent store:
status = getLicenseExtAPIKeyCookieStr(licenseInfo, strCookie, sizeof(strCookie));
}
// Free license key context
freeLicenseInfo(licenseInfo);
To check the license in the steady state, your application's license checking logic will read the last-saved key cookie from persistent store and then invoke the checkExtAPILicense API call, following which it will save the new key cookie in persistent store, as follows:
// includes
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <ezLicenseInfo.h>
#include <ezLicenseExtAPI.h>
:
// Check the last-obtained license activation record
// that you read from persistent store eg. a registry entry.
// Bump up usage count by one, by specifying -1 for the quota-increment parameter.
void *licenseInfo = NULL;
int status =
checkExtAPILicense(
strCookie, NULL, NULL, 0, -1, 0, 0, userName, 0,
"FileManagerProduct", "rTxWsuxjr4/s3J=",
NULL, NULL, TRUE,
&licenseInfo);
if (status < 0) { // error
:
:
} else {
// extract and save key cookie in persistent store:
status = getLicenseExtAPIKeyCookieStr(licenseInfo, strCookie, sizeof(strCookie));
}
// Free license key context
freeLicenseInfo(licenseInfo);
To deactivate the license (for example at the time of uninstallation), your application's deactivation logic will read the last-saved key cookie from persistent store and then invoke the deactivateLicense API call, as follows:
// includes
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <ezLicenseInfo.h>
#include <ezLicenseExtAPI.h>
:
// Deactivate the last-obtained license activation record
// that you read from persistent store eg. a registry entry.
int status =
deactivateExtAPILicense(
strCookie,
"FileManagerProduct", "rTxWsuxjr4/s3J=",
NULL, NULL, TRUE);
if (status < 0) { // error
:
:
}
// delete key cookie from persistent store
The cdemoextapi.c application, available in the cpp/demo directory,
is an application that performs normal or deferred-mode license checks according to
whether and what auxiliary license key is provided.
Deferred-mode functionality is turned on by specifying the appropriate pair of keys: the actual key generated by you, and the enabling auxiliary key generated by Agilis and provided to you, as follows:
Deferred time-limited licensing:
This the anonymous-trial-licensing use case, where you may want to provide
a single self-contained binary file, together with a single set of keys,
for all evaluators to access either by downloading or installing from a
a single distribution medium, such that each installation is time-limited
to a duration controlled by you relative to the time the user initiates
trial licensing, without any communication between you and the trial user.
You generate a single key, which is not node locked, and which
has a EZLM:KEY-EXPIRE-DAYS option whose value you define to be the
desired license duration in days from the time of activation.
Correspondingly, Agilis provides you an auxiliary key that has embedded in
it an upper limit on relative expiration days. The effective relative-time-limited
license duration is the lower of the two values. In your application
logic, you provide the auxiliary key parameter to the license activation
API call. If you want the license to node-lock to the application installation
at the time of activation, your application specifies a TRUE value for the
deferredNodeLock parameter.
Deferred node-locked licensing:
This the production-licensing use case, where you want to issue
production license keys to end customers, such that you achieve the
best of all worlds: your keys are node-locked to the end-customer
installation and at the same time you don't need to collect node-locking
information from your customer - instead you ensure the key you
generate can only be installed within a narrow time window that
starts the moment you generate the key.
In response to each customer order, you generate a key, which is not node locked, and which
has a EZLM:KEY-EXPIRE-SHELF-LIFE-HRS option whose value you define to be the
desired shelf life in hours from the time of key generation, which
represents the period during which the key can be installed
by your end customer.
Correspondingly, Agilis provides you an auxiliary key that has embedded in
it the appropriate authorization to issue deferred node-locked licenses.
In the application integration logic, your application specifies
a TRUE value for the deferredNodeLock parameter.
The objective behind coding for security is to thwart the following types of attacks:
Cross-product key use: when an end customer uses an EasyLicenser-generated key
intended for another licensed product with your product instead of paying for and
acquiring an appropriate license for your product as well.
The defense against this attack is to generate access controlled keys and code
your application to use the access control enabled license key checking API's.
Key cloning: when an end customer's programmer writes code to analyze a valid
license key obtained from you in order to utilize EasyLicenser for generating
additional keys for your product on unlicensed machines.
The access controlled key mechanism also serves as a defense against this attack,
since the encrypted key contents, including product options, custom cookie and
custom key, are encrypted with a private key that is not known to the customer or
to you, and decrypted with a corresponding public key that is known to you but not
to your customer.
Bypassing license key checks: when an end customer's programmer reverse
engineers and debugs your application and / or the EasyLicenser runtime library,
alters the license key checking logic in reverse engineered code and rebuilds the
application / runtime library so it can be used without a valid license key.
The EasyLicenser runtime provides the following defenses to protect your
application from this type of attack:
Verifying EasyLicenser run time's actual digital signature against one
provided by you or Agilis. Any changes to the library cause the signatures
to mismatch. Your application performs the signature verification upon
program startup or when a library is dynamically loaded the first time.
You can also use the same digital signature mechanism to protect your own
libraries from tampering. In this case, you will necessarily have to generate
your own signatures.
Utilizing EasyLicenser's secure API. The secure API forces a validation and
exchange of encrypted key cookies upon each license key check such that
the key cookies change in value each time.
Utilizing a custom key handler to implement a three-way shared secret and
throw a signal. The custom key can contain a secret known only to your application
which passes it in encrypted form as a run time context to the license key
checking API which in turn calls back to your handler. Your handler can also
signal a license key check event such that the main application code requires
the signal to be raised in order for the license checking to be declared to
be successful.
This is illustrated in the previous examples. No programming is required beyond passing the product name and application password public keys as parameters to an access-control API. The product name exactly corresponds to the name of the product that you specified in the License Manager GUI. The application password public key is the value displayed in the Product Details screen in the License Manager GUI when you define an application password for the product, and the product definition is selected at the time of key generation. If the key is not access-controlled, you can pass NULL values for the parameters. If the key is access-controlled, the parameter values are mandatory. For maximum security, specify a value of TRUE for the "strict password check" parameter.
The secure API accepts an encrypted key cookie parameter
that is initialized at product activation time using a create
key cookie seed API call, and saved by the application in persistent
store. Every time a license key check is performed, for example upon
application startup, the saved key cookie os provided to the secure
license key check API call, which validates it and produces and returns
an updated key cookie if the license key check is successful. The
application replaces the previous key cookie with the new key cookie.
If the key cookie is tampered with, or the system clock is turned back to
before the timestamp contained in the last-saved key cookie, the
license key check will fail regardless of the validity of the license key.
The secure API optionally accepts an application-defined custom
exception handler.
The secure API's key cookie also securely manages application license state that changes
at run time with successive license key checks. This state information is protected
from tampering by the same mechanisms that protect the key cookie. The specifics
of using key cookies for secure state management are described below under
Coding For Automatic State Management.
For a detailed illustration of how the secure API is used in conjunction with
key cookies, please refer to the
cdemosecure.cpp source code.
Note however that for automatic state management, the preferred approach is to use the
higher-level extended API instead.
The secure API and key cookie mechanism is also used in an enhanced mode to automatically manage
license state that changes with successive use at the end customer site. Quota consumption is
implicitly tracked in the key cookie as a function of a quota increment that is specified to
the license key check call. To differentiate the quota increment from the pre-EasyLicenser 2.0
usage where the quota value always represented a cumulative quota value maintained by the
application, a quota increment is represented by a negative value.
In addition to automatically managing quota consumption, the key cookie can also track arbitrary
application license state that is supplied at the time of key cookie creation or a secure license
key check.
The license state contents of the key cookie can be retrieved through a set of getter
methods provided for the purpose.
For a detailed illustration of how the secure API is used in conjunction with
key cookies in enhanced mode to automatically manage license state, please refer to
the cdemostate.c source code.
The above objectives can be met with less coding if you use the higher-level extended API instead of the secure API.
The cdemoextapi.c source code illustrates how to
use the extended API.
The mechanism for protection from client library spoofing is a
dynamic digital signature: at your development environment,
you generate a digital signature for the EasyLicenser (and / or your own) library that is
unique to your application and platform, and is based on a password specified by you.
For the EasyLicenser runtime library, you do not have to use the digital signature
provided to you by Agilis. You then
package or embed with your application the public-key-encrypted versions
of your password and signature, and then use these to securely double-
check the signature of the library at run time at your
end customer's site, as follows:
ISV development environment:
Outside of your actual application, invoke the
makeLibDigest function defined in
cpp/include/Signature.h and
contained in the ilscrypt10 static library,
providing as input parameters the EasyLicenser runtime library file name, a password
unique to your application and known only to your developers, and the EasyLicenser
C/C++ library product name EzlmCppLibrary,
as follows:
#include <Signature.h>
:
// Invocation returns a vector of 3 strings:
// signature, public-key-encrypted signature, public-key-encrypted password
char sigbuf[SIGBUFSIZE]; // buffer to receive signature
char encsigbuf[SIGBUFSIZE]; // buffer to receive public-key-encrypted signature
char encpwdbuf[SIGBUFSIZE]; // buffer to receive public-key-encrypted password
if (makeLibDigest(
"ezLicenserlib20", // shared library name w/o extension
"myezlmsecret", // your unique secret password
"EzlmCppLibrary", // product name
TRUE, // indicate this is running in ISV environment
sigbuf, sizeof(sigbuf), // output signature buffer
encsigbuf, sizeof(encsigbuf), // output encrypted signature buffer
encpwdbuf, sizeof(encpwdbuf)) != 0) { // output encrypted password buffer
printf("%s\n", sigbuf); // error msg is in signature buffer
exit(1);
}
You can also use the platform-specific makelibdigest
command line utility instead of coding against the API. In either case, you will embed
the public key encrypted password into your application, and you will embed or otherwise
arrange your application to be parameterized to accept either the signature or its
public key encrypted form. For security, it is recommend that you parameterize your
application to accept the public key encrypted form of the signature so you don't
have to keep it secret and so you only need change a data file whenever the EasyLicenser
runtime library is updated. The coding tradeoff is that your application will need to make
an extra call at run time to perform an additional public key encryption call.
Runtime application environment:
Code your application to invoke makeLibDigest
similar to the above, except that with this API call, provide the
public-key-encrypted password and indicate that this is a run time invocation:
#include <Signature.h>
#include <PkCrypt.h>
:
// Invocation returns a vector of 3 strings:
// signature, public-key-encrypted signature, public-key-encrypted password
char sigbuf[SIGBUFSIZE]; // buffer to receive signature
char encsigbuf[SIGBUFSIZE]; // buffer to receive public-key-encrypted signature
char encpwdbuf[SIGBUFSIZE]; // buffer to receive public-key-encrypted password
if (makeLibDigest(
"ezLicenserlib20", // shared library name w/o extension
"UYqqRp+iT5asTpa7", // pk-encrypted password corresponding to "myezlmsecret"
"EzlmCppLibrary", // product name - keep consistent
FALSE, // indicate this is not running in ISV environment
sigbuf, sizeof(sigbuf), // output signature buffer
encsigbuf, sizeof(encsigbuf), // output encrypted signature buffer
encpwdbuf, sizeof(encpwdbuf)) != 0) { // output encrypted password buffer
printf("%s\n", sigbuf); // error msg is in signature buffer
exit(1);
}
If you stored the original actual signature in its public key encrypted form
as recommended, first reconstruct the encrypted signature and check it in
order to detect spoofing of the cryptographic library itself. Use the
EasyLicenser library product's public key for encryption:
char prodPubKey[SIGBUFSIZE];
if (makePublicKey("EzlmCppLibrary", prodPubKey, sizeof(prodPubKey))) {
// error making public key
exit(1); // internal error
}
char encrSig[SIGBUFSIZE]; // buffer to receive encrypted signature
if (encryptWithPublicKey(sigbuf,
prodPubKey, // product public key
encrSig, sizeof(encrSig)) { // encryption output buffer
exit(1); // internal encryption error
}
if (strcmp(encrSig,encrsigbuf)) {
printf("*** Spoofed signature / crypto library ***\n");
exit(1);
}
Next, compare the resulting signature with the saved signature:
if (strcmp(encrSig, savedOriginalSignature) {
printf("*** Spoofed EasyLicenser library ***\n");
exit(1);
}
You should perform the check on the library prior to using any of its
functions, for example upon program startup.
There is necessarily a negative consequence of verifying signatures:
a new release of the library is necessarily accompanied by an updated
signature that requires a new release of your application unless
you parameterize your application to accept a signature parameter,
for example in a configuration file.
To compile and link your application modules that perform license management, include the appropriate header files in cpp/include, and link with the libraries in the platform-specific subdirectory of cpp/lib.
Always include the ezLicenseInfo.h header file. Also include ezLicenseExtAPI.h if you are using the extended API. If you are performing explicit encryption operations, also include PkCrypt.h. Include Signature.h if invoking the makeLibDigest API call.
Link your object modules with the ilscrypt10 static library and the ezLicenserlibVV dynamic library (or its import library, if your platform is Windows), both located at the platform-specific subdirectory of cpp/lib.
The platform-specific shared library will need to accompany your product distribution and be included in your product's library path environment variable at your end customer site.
Refer to the C/C++ header files located at the cpp/include directory for specific information on the EasyLicenser C/C++ API calls that you will use while writing your product’s license-enabling code.