# Using Dinkey Pro/FD with Java

Protection checks in Java are implemented using DinkeyPro.class to communicate with the dongle via the appropriate native library (DPJava.dll on 32-bit Windows, libDPJava64.so on 64-bit Linux, etc.). You should lock these native libraries with the API method using DinkeyAdd as described in the user manual, and distribute the locked libraries with your software.

The `DinkeyPro` class provides a Java wrapper around the Dinkey Pro/FD API, which is implemented by native libraries. If you are not familiar with calling native libraries, it is recommended that you read the Java documentation on the subject, especially the documentation for `System.loadLibrary()` and `System.load()`, and how Java uses the system property `java.library.path` to locate native libraries.

The native libraries and the `DinkeyPro` class are part of the `uk.microcosm.dinkeydongle` package. See the documentation for your development environment for details of how to include and reference this package in your project. dinkeydongle.jar provides all of the Java classes in the `uk.microcosm.dinkeydongle` package in a single JAR file. This allows you to import the package much more easily in many Java IDEs. Note that the native libraries are not included in the JAR file. You will need to distribute with your software locked copies of the native libraries for every platform that your software supports.

Do not specify a calling program when locking the native libraries. The calling program for Java software is the user's JVM, which will be different for different users.

Java bytecode is more easily decompiled than native code. For maximum security, it is recommended that you obfuscate your Java code using a third-party tool.

## The DinkeyPro Class

Instances of `DinkeyPro` contain an internal DRIS. Most of this structure's members are exposed as public fields that can be directly accessed. Others must be accessed via `get...()` and `set...()` methods: see below for details. As Java does not have unsigned types, DRIS members that are documented as unsigned integers in the user manual are represented by `long` fields in the `DinkeyPro` class.

The `header` and `size` DRIS members are set automatically. You do not need to set these fields in your code.

`rw_data_ptr` is not used in Java. To use an API function that passes data to/from the dongle, you must use the `checkProtection(byte[] data)` method and also set the `USE_FUNCTION_ARGUMENT` flag.

### Fields

Possible values for the `function` DRIS field, as documented in the user manual:

- `static final int PROTECTION_CHECK`
- `static final int EXECUTE_ALGORITHM`
- `static final int WRITE_DATA_AREA`
- `static final int READ_DATA_AREA`
- `static final int ENCRYPT_USER_DATA`
- `static final int DECRYPT_USER_DATA`
- `static final int FAST_PRESENCE_CHECK`
- `static final int STOP_NET_USER`

Possible values for the `flags` DRIS field, as documented in the user manual:

- `static final int DEC_ONE_EXEC`
- `static final int DEC_MANY_EXECS`
- `static final int START_NET_USER`
- `static final int USE_FUNCTION_ARGUMENT`
- `static final int CHECK_LOCAL_FIRST`
- `static final int CHECK_NETWORK_FIRST`
- `static final int USE_ALT_LICENCE_NAME`
- `static final int DONT_SET_MAXDAYS_EXPIRY`
- `static final int MATCH_DONGLE_NUMBER`
- `static final int DONT_RETURN_FD_DRIVE`

Possible values for the `type` DRIS field, as documented in the user manual:

- `static final int TYPE_PRO`
- `static final int TYPE_FD`

Possible values for the `model` DRIS field, as documented in the user manual:

- `static final int MODEL_LITE`
- `static final int MODEL_PLUS`
- `static final int MODEL_NET5`
- `static final int MODEL_NETU`

Possible values for the `net_users` DRIS field, as documented in the user manual:

- `static final int UNLIMITED_NET_USERS`

Directly accessible DRIS fields, as documented in the user manual:

- `int seed1`
- `int seed2`
- `int function`
- `int flags`
- `long execs_decrement`
- `int data_crypt_key_num`
- `int rw_offset`
- `int rw_length`
- `int var_a`
- `int var_b`
- `int var_c`
- `int var_d`
- `int var_e`
- `int var_f`
- `int var_g`
- `int var_h`
- `int alg_number`
- `int ret_code`
- `int ext_err`
- `int type`
- `int model`
- `int sdsn`
- `long dongle_number`
- `int update_number`
- `long data_area_size`
- `int max_alg_num`
- `int execs`
- `int exp_day`
- `int exp_month`
- `int exp_year`
- `long features`
- `int net_users`
- `int alg_answer`
- `long fd_capacity`
- `int swkey_type`
- `int swkey_exp_day`
- `int swkey_exp_month`
- `int swkey_exp_year`

Fields used to access information returned by `DDGetNetUserList()`:

- `int numNetUsers` - the current number of network users when `DDGetNetUserList()` was called.
- `int queryNetUsersExtErr` - contains additional error information if `DDGetNetUserList()` returns failure.
- `String[] licenceNames` - the names of the licences currently used by network users.
- `String[] userNames` - the usernames of the current network users.
- `String[] computerNames` - the computer names of the current network users.
- `String[] ipAddresses` - the IP addresses of the current network users.

The string arrays should be used in combination, i.e. `licenceNames[0]`, `userNames[0]`, `computerNames[0]` and `ipAddresses[0]` together describe a single network user.

### Constructors

These constructors can throw any exception thrown by `System.loadLibrary()` and `System.load()`. See the documentation for those methods for details.

#### DinkeyPro()

Creates a new DinkeyPro instance and calls `System.loadLibrary()` to load the native library using the default filename. The library must be located in one of the paths specified in the `java.library.path` system property. The exact filename is implementation-dependent, but the most common names are:

- 32-bit Windows - DPJava.dll
- 64-bit Windows - DPJava64.dll
- 32-bit Linux - libDPJava.so
- 64-bit Linux - libDPJava64.so
- 64-bit macOS - libDPJava64.dylib

The members of the instance's internal DRIS are initialised to random values.

#### DinkeyPro(String libName)

Creates a new DinkeyPro instance and calls `System.loadLibrary(libName)` to load the native library. The library must be located in one of the paths specified in the `java.library.path` system property. If `System.loadLibrary(libName)` fails, it then calls `System.load(libName)`. Use this version of the constructor if you rename the native libraries (recommended), or if you need to specify the absolute path to the library.

The members of the instance's internal DRIS are initialised to random values.

### Methods

#### int checkProtection()

Calls `DDProtCheck()` in the native library using the internal DRIS. Returns zero on success, or a value indicating the cause of the error on failure.

#### int checkProtection(byte[] data)

Calls `DDProtCheck()` in the native library using the internal DRIS. `data` is passed to the API (e.g. when writing to the dongle data area), or acts as a buffer filled by the API (e.g. when reading from the dongle data area). When using this method you must also set the `USE_FUNCTION_ARGUMENT` flag. Returns zero on success, or a value indicating the cause of the error on failure.

#### int queryNetUsers(int maxUsersToQuery)

Calls `DDGetNetUserList()` in the native library. `maxNetUsersToQuery` specifies the maximum number of current network users to return information about. Use this version of this method to get information about the current network users for the protected software's licence (if protected with the per licence network users option), or all licences in the dongle (if protected with the per product network users option). Returns zero on success, or a value indicating the cause of the error on failure.

#### int queryNetUsers(String licenceName, int maxUsersToQuery)

Calls `DDGetNetUserList()` in the native library. `maxNetUsersToQuery` specifies the maximum number of current network users to return information about. Use this version of this method to get information about the current network users for the licence specified by `licenceName`. Returns zero on success, or a value indicating the cause of the error on failure.

#### void reset()

Set all members of the internal DRIS to random values.

#### String getProdCode()

Return the `prodcode` member of the internal DRIS as a Java string.

#### String getFdDrive()

Return the `fd_drive` member of the internal DRIS as a Java string.

#### void setAltLicenceName(String altLicenceName)

Assign the value of `altLicenceName` to the `alt_licence_name` member of the internal DRIS.

#### void cryptDris(int encryptionParameter1, int encryptionParameter2, int encryptionParameter3)

Encrypt/decrypt the internal DRIS. `encryptionParameter1`, `encryptionParameter2` and `encryptionParameter3` must match the parameters specified for DRIS encryption in DinkeyAdd.

#### void cryptApiData(byte[] data, int algAnswer)

Encrypt/decrypt `checkProtection()`'s `data` parameter using the result of the R/W algorithm. The option to take data encryption parameters from the R/W algorithm must also be selected in DinkeyAdd when adding protection, and `algAnswer` must be the result of an algorithm that matches the R/W algorithm specified there.

#### void cryptApiData(byte[] data, int encryptionParameter1, int encryptionParameter2, int encryptionParameter3)

Encrypt/decrypt `checkProtection()`'s `data` parameter using constant parameters. The option to use constant data encryption parameters must be selected in DinkeyAdd when adding protection, and `encryptionParameter1`, `encryptionParameter2` and `encryptionParameter3` must match the parameters specified there.

## Java Example Files

- DPSample.java - various examples of using the `DinkeyPro` class.

## Supported Versions

All parts of the `uk.microcosm.dinkeydongle` package support Java platforms version 5 and newer.

## Try It Yourself

The sample code is designed to teach you how to use the Dinkey Pro/FD API in Java programs. Do not copy the examples verbatim into your own code. Experiment with the sample code to understand how the API works, and read the chapter Increasing Your Protection in the user manual for many suggestions on how to make the best use of the API features.

DPSample.java gives simple examples of performing a protection check, as well as using various other features of Dinkey Pro/FD. To run the DPSample program you will first need to use DinkeyAdd to produce a locked copy of the native library for your platform, and program a dongle (if you are using Plus or Net dongles). Place the locked library in one of the paths specified by your Java environment's `java.library.path` system property. Browse the examples in DPSample.java to see how different features can be used. All the examples follow the same basic pattern:

1. Create a DinkeyPro instance and set up its internal DRIS with the relevant information.
2. Call the API.
3. Use the information returned in the internal DRIS.

Uncomment the calls at the top of the `main()` method in DPSample.java to enable the examples of different features, then recompile and run DPSample to run the examples.

Parts of the sample code marked with `!!!!` must be customised with your own functions or values for some features to work correctly. Not all features are supported by all dongle models. See the user manual for more information.