Add Original SDK

This commit is contained in:
2026-05-06 07:47:36 +02:00
parent 2915e04380
commit 0ed627517a
674 changed files with 89334 additions and 0 deletions

View File

@@ -0,0 +1,612 @@
// Example use of the Dinkey Pro/FD API in Java.
// Copyright 2018 Microcosm Ltd.
import uk.microcosm.dinkeydongle.DinkeyPro;
import java.util.Arrays; // For Arrays.toString()
class DPSample
{
static final String MY_PRODCODE = "DEMO"; // !!!! Replace "DEMO" with the product code that you specify when adding protection with DinkeyAdd.
static final int MY_SDSN = 10101; // !!!! "10101" is the SDSN used by the demo SDK and demo dongles.
// If not using a demo, replace "10101" with your own SDSN here.
static final int DRIS_ENCRYPTION_PARAMETER_1 = 123; // !!!! If you enable DRIS encryption when adding protection with DinkeyAdd,
static final int DRIS_ENCRYPTION_PARAMETER_2 = 212; // replace these values with the encryption parameters that you specify.
static final int DRIS_ENCRYPTION_PARAMETER_3 = 97;
public static void main(String[] args)
{
// Each of the methods below demonstrates different API functionality.
// Uncomment the appropriate methods to execute the examples.
// See the comments in each method for more details about the features that they demonstrate.
protCheck();
// protCheckWithAlg();
// writeDataArea();
// readDataArea();
// encryptUserData();
// protCheckEnc();
// writeDataAreaEnc();
// readDataAreaEnc();
// encryptUserDataEnc();
// displayNetUsers();
}
// An example of a basic protection check
static void protCheck()
{
int retCode;
// Create a DinkeyPro instance that uses the default library name, DPJava.
// All DRIS fields are initialised to random values.
DinkeyPro ddpro = new DinkeyPro();
// You can use an alternative library name like this:
// DinkeyPro ddpro = new DinkeyPro("MyName");
// The manner in which the library name is mapped to the actual system library is system dependent,
// but common behaviour is that Java will attempt to locate and load MyName.dll on Windows, libMyName.dylib on macOS,
// or libMyName.so on Linux.
// You can also specify the full path to the library, if it is not located in one of the paths specified by java.library.path,
// or uses a non-standard filename:
// Dinkey ddpro = new DinkeyPro("~/Unusual Folder For Libraries/nonstandardname.jnilib");
// Initialise the DRIS
ddpro.function = DinkeyPro.PROTECTION_CHECK;
ddpro.flags = DinkeyPro.DEC_ONE_EXEC | DinkeyPro.START_NET_USER;
// Call the API
retCode = ddpro.checkProtection();
// Check the return value
if (retCode != 0)
{
displayError(retCode, ddpro.ext_err);
return;
}
// ...
// You can check other values from the DRIS in other parts of your program to improve security.
// For example:
// Check the SDSN
if (ddpro.sdsn != MY_SDSN)
{
System.out.println("Incorrect SDSN! Have you replaced '10101' with your SDSN in the sample code?");
return;
}
// Check the product code
if (!(ddpro.getProdCode().equals(MY_PRODCODE)))
{
System.out.println("Incorrect Product Code! Please modify your source code so that MY_PRODCODE is set to be the Product Code in the dongle.");
return;
}
System.out.println("Protection check successful.");
return;
}
// An example of a protection check that also executes an algorithm stored in the dongle.
// The best way to use this feature is to identify lines of code in your program
// that can be represented by algorithms stored in the dongle,
// and replace these lines with calls to the API.
// Lite dongle users cannot change the algorithm stored in the dongles,
// so should calculate the algorithm in their own code and compare the result with the one returned by the API,
// as in this example.
static void protCheckWithAlg()
{
int retCode;
DinkeyPro ddpro = new DinkeyPro();
// Initialise the DRIS
ddpro.function = DinkeyPro.EXECUTE_ALGORITHM;
ddpro.flags = 0;
ddpro.alg_number = 1; // The algorithm to execute. Lite dongles ignore this field, as they contain only 1 algorithm
ddpro.var_a = 1; // The input variables to use in the algorithm
ddpro.var_b = 2;
ddpro.var_c = 3;
ddpro.var_d = 4;
ddpro.var_e = 5;
ddpro.var_f = 6;
ddpro.var_g = 7;
ddpro.var_h = 8;
// Call the API
retCode = ddpro.checkProtection();
// Check the return value
if (retCode != 0)
{
displayError(retCode, ddpro.ext_err);
return;
}
// ...
// Check the algorithm result in another part of your program to improve security.
// !!!! Ensure the myAlgorithm() method matches the algorithm that was executed by the protection check!
if (myAlgorithm(ddpro.var_a, ddpro.var_b, ddpro.var_c, ddpro.var_d, ddpro.var_e, ddpro.var_f, ddpro.var_g, ddpro.var_h) != ddpro.alg_answer)
{
System.out.println("Error! The algorithm result was not as expected.");
return;
}
System.out.println("Protection check with algorithm successful.");
return;
}
// An example of a protection check that also writes data to the dongle's secure data area.
// This feature is not supported by Lite dongles.
// Make sure you specify a large enough data area size when adding protection with DinkeyAdd!
static void writeDataArea()
{
int retCode;
DinkeyPro ddpro = new DinkeyPro();
byte[] data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // Data to write
// Initialise the DRIS
ddpro.function = DinkeyPro.WRITE_DATA_AREA;
ddpro.flags = DinkeyPro.USE_FUNCTION_ARGUMENT; // Java uses DDProtCheck()'s data parameter, so this flag must be set
ddpro.rw_offset = 0; // Index to start writing at. Indices start at zero
ddpro.rw_length = data.length; // The number of bytes to be written
// Call the API
retCode = ddpro.checkProtection(data);
// Check the return value
if (retCode != 0)
{
displayError(retCode, ddpro.ext_err);
return;
}
// You can inspect the dongle with DinkeyLook to see that the data has been written to the dongle
System.out.println("Writing data successful.");
return;
}
// An example of a protection check that also reads data from the dongle's secure data area.
// This feature is not supported by Lite dongles.
// Make sure you specify a large enough data area size when adding protection with DinkeyAdd!
static void readDataArea()
{
int retCode;
DinkeyPro ddpro = new DinkeyPro();
byte[] data = new byte[10];
// Initialise the DRIS
ddpro.function = DinkeyPro.READ_DATA_AREA;
ddpro.flags = DinkeyPro.USE_FUNCTION_ARGUMENT; // Java uses DDProtCheck()'s data parameter, so this flag must be set
ddpro.rw_offset = 0; // Index to start reading from. Indices start at zero
ddpro.rw_length = data.length; // The number of bytes to read
// Call the API
retCode = ddpro.checkProtection(data);
// Check the return value
if (retCode != 0)
{
displayError(retCode, ddpro.ext_err);
return;
}
System.out.println("Reading data successful: " + Arrays.toString(data));
return;
}
// An example of protection checks that encrypt/decrypt your data.
// This feature is not supported by Lite dongles.
static void encryptUserData()
{
int retCode;
DinkeyPro ddpro = new DinkeyPro();
byte[] data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // The data to be encrypted
byte[] originalData = data.clone(); // A copy of the data for displaying later
byte[] encryptedData;
// Initialise the DRIS
ddpro.function = DinkeyPro.ENCRYPT_USER_DATA;
ddpro.flags = DinkeyPro.USE_FUNCTION_ARGUMENT; // Java uses DDProtCheck()'s data parameter, so this flag must be set
ddpro.rw_length = data.length; // The number of bytes to be encrypted
ddpro.data_crypt_key_num = 1; // The encryption key to use
// Call the API
retCode = ddpro.checkProtection(data);
// Check the return value
if (retCode != 0)
{
displayError(retCode, ddpro.ext_err);
return;
}
encryptedData = data.clone(); // A copy of the encrypted data for displaying later
// Initialise the DRIS
ddpro.reset(); // Reset the DRIS fields with random values
ddpro.function = DinkeyPro.DECRYPT_USER_DATA;
ddpro.flags = DinkeyPro.USE_FUNCTION_ARGUMENT; // Java uses DDProtCheck()'s data parameter, so this flag must be set
ddpro.rw_length = data.length;
ddpro.data_crypt_key_num = 1; // This must be the same key used to encrypt the data
// Call the API
retCode = ddpro.checkProtection(data);
// Check the return value
if (retCode != 0)
{
displayError(retCode, ddpro.ext_err);
return;
}
System.out.println("Data encryption successful.");
System.out.println("Original data: " + Arrays.toString(originalData));
System.out.println("Encrypted data: " + Arrays.toString(encryptedData));
System.out.println("Decrypted data: " + Arrays.toString(data));
return;
}
// An example of a protection check that uses DRIS encryption for extra security.
static void protCheckEnc()
{
int retCode;
DinkeyPro ddpro = new DinkeyPro();
// Initialise the DRIS
ddpro.function = DinkeyPro.PROTECTION_CHECK;
ddpro.flags = 0;
// Encrypt the DRIS
ddpro.cryptDris(DRIS_ENCRYPTION_PARAMETER_1, DRIS_ENCRYPTION_PARAMETER_2, DRIS_ENCRYPTION_PARAMETER_3);
// Call the API
retCode = ddpro.checkProtection();
// Decrypt the DRIS
ddpro.cryptDris(DRIS_ENCRYPTION_PARAMETER_1, DRIS_ENCRYPTION_PARAMETER_2, DRIS_ENCRYPTION_PARAMETER_3);
// Check the return value
if (retCode != 0)
{
displayError(retCode, ddpro.ext_err);
return;
}
// ...
// You can check other values from the DRIS in other parts of your program to improve security.
// For example:
// Check the SDSN
if (ddpro.sdsn != MY_SDSN)
{
System.out.println("Incorrect SDSN! Have you replaced '10101' with your SDSN in the sample code?");
return;
}
// Check the product code
if (!(ddpro.getProdCode().equals(MY_PRODCODE)))
{
System.out.println("Incorrect Product Code! Please modify your source code so that MY_PRODCODE is set to be the Product Code in the dongle.");
return;
}
System.out.println("Protection check successful.");
return;
}
// An example of a protection check that also writes data to the dongle's secure data area.
// This feature is not supported by Lite dongles.
// Make sure you specify a large enough data area size when adding protection with DinkeyAdd!
// This method also uses DRIS encryption and data encryption for extra security.
// You must select these options on the Extra Security tab of DinkeyAdd for this method to work correctly!
static void writeDataAreaEnc()
{
int retCode, algAnswer;
DinkeyPro ddpro = new DinkeyPro();
byte[] data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // The data to be written
// Initialise the DRIS
ddpro.function = DinkeyPro.WRITE_DATA_AREA;
ddpro.flags = DinkeyPro.USE_FUNCTION_ARGUMENT; // Java uses DDProtCheck()'s data parameter, so this flag must be set
ddpro.rw_offset = 0; // Index to start writing at. Indices start at zero
ddpro.rw_length = data.length; // The number of bytes to write
// If taking data encryption parameters from the R/W algorithm:
// Calculate the R/W algorithm result
// The input variables were initialised to random values when ddpro was created
algAnswer = myRwAlgorithm(ddpro.var_a, ddpro.var_b, ddpro.var_c, ddpro.var_d, ddpro.var_e, ddpro.var_f, ddpro.var_g, ddpro.var_h);
// Use the algorithm result to encrypt the data to be written to the dongle
ddpro.cryptApiData(data, algAnswer);
// If using constant data encryption parameters:
// ddpro.cryptApiData(data, DATA_ENCRYPTION_PARAMETER_1, DATA_ENCRYPTION_PARAMETER_2, DATA_ENCRYPTION_PARAMETER_3);
// Encrypt the DRIS
ddpro.cryptDris(DRIS_ENCRYPTION_PARAMETER_1, DRIS_ENCRYPTION_PARAMETER_2, DRIS_ENCRYPTION_PARAMETER_3);
// Call the API
retCode = ddpro.checkProtection(data);
// Decrypt the DRIS
ddpro.cryptDris(DRIS_ENCRYPTION_PARAMETER_1, DRIS_ENCRYPTION_PARAMETER_2, DRIS_ENCRYPTION_PARAMETER_3);
// Check the return value
if (retCode != 0)
{
displayError(retCode, ddpro.ext_err);
return;
}
System.out.println("Writing data successful.");
return;
}
// An example of a protection check that also reads data from the dongle's secure data area.
// This feature is not supported by Lite dongles.
// Make sure you specify a large enough data area size when adding protection with DinkeyAdd!
// This method also uses DRIS encryption and data encryption for extra security.
// You must select these options on the Extra Security tab of DinkeyAdd for this method to work correctly!
static void readDataAreaEnc()
{
int retCode, algAnswer;
DinkeyPro ddpro = new DinkeyPro();
byte[] data = new byte[10];
// Initialise the DRIS
ddpro.function = DinkeyPro.READ_DATA_AREA;
ddpro.flags = DinkeyPro.USE_FUNCTION_ARGUMENT; // Java uses DDProtCheck()'s data parameter, so this flag must be set
ddpro.rw_offset = 0; // Index to start reading from. Indices start at zero
ddpro.rw_length = data.length; // The number of bytes to read
// Encrypt the DRIS
ddpro.cryptDris(DRIS_ENCRYPTION_PARAMETER_1, DRIS_ENCRYPTION_PARAMETER_2, DRIS_ENCRYPTION_PARAMETER_3);
// Call the API
retCode = ddpro.checkProtection(data);
// Decrypt the DRIS
ddpro.cryptDris(DRIS_ENCRYPTION_PARAMETER_1, DRIS_ENCRYPTION_PARAMETER_2, DRIS_ENCRYPTION_PARAMETER_3);
// Check the return value
if (retCode != 0)
{
displayError(retCode, ddpro.ext_err);
return;
}
// If taking data encryption parameters from the R/W algorithm:
// Calculate the R/W algorithm result
// The input variables were initialised to random values when ddpro was created
algAnswer = myRwAlgorithm(ddpro.var_a, ddpro.var_b, ddpro.var_c, ddpro.var_d, ddpro.var_e, ddpro.var_f, ddpro.var_g, ddpro.var_h);
// Use the algorithm result to decrypt the data read from the dongle
ddpro.cryptApiData(data, algAnswer);
// If using constant data encryption parameters:
// ddpro.cryptApiData(data, DATA_ENCRYPTION_PARAMETER_1, DATA_ENCRYPTION_PARAMETER_2, DATA_ENCRYPTION_PARAMETER_3);
System.out.println("Reading data successful: " + Arrays.toString(data));
return;
}
// An example of protection checks that encrypt/decrypt your data.
// This feature is not supported by Lite dongles.
// This method also uses DRIS encryption and data encryption for extra security.
// You must select these options on the Extra Security tab of DinkeyAdd for this method to work correctly!
static void encryptUserDataEnc()
{
int retCode, algAnswer;
DinkeyPro ddpro = new DinkeyPro();
byte[] data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // The data to be encrypted
byte[] originalData = data.clone(); // A copy of the data for displaying later
byte[] encryptedData;
// Initialise the DRIS
ddpro.function = DinkeyPro.ENCRYPT_USER_DATA;
ddpro.flags = DinkeyPro.USE_FUNCTION_ARGUMENT; // Java uses DDProtCheck()'s data parameter, so this flag must be set
ddpro.rw_length = data.length; // The number of bytes to be encrypted
ddpro.data_crypt_key_num = 1; // The encryption key to use
// If taking data encryption parameters from the R/W algorithm:
// Calculate the R/W algorithm result
// The input variables were initialised to random values when ddpro was created
algAnswer = myRwAlgorithm(ddpro.var_a, ddpro.var_b, ddpro.var_c, ddpro.var_d, ddpro.var_e, ddpro.var_f, ddpro.var_g, ddpro.var_h);
// Use the algorithm result to encrypt the data passed to the API
ddpro.cryptApiData(data, algAnswer);
// If using constant data encryption parameters:
// ddpro.cryptApiData(data, DATA_ENCRYPTION_PARAMETER_1, DATA_ENCRYPTION_PARAMETER_2, DATA_ENCRYPTION_PARAMETER_3);
// Encrypt the DRIS
ddpro.cryptDris(DRIS_ENCRYPTION_PARAMETER_1, DRIS_ENCRYPTION_PARAMETER_2, DRIS_ENCRYPTION_PARAMETER_3);
// Call the API
retCode = ddpro.checkProtection(data);
// Decrypt the DRIS
ddpro.cryptDris(DRIS_ENCRYPTION_PARAMETER_1, DRIS_ENCRYPTION_PARAMETER_2, DRIS_ENCRYPTION_PARAMETER_3);
// Do not call cryptApiData() here to decrypt the data received from the API!
// The data has been encrypted by the dongle hardware, so the API will not apply an unnecessary second layer of encryption
// Check the return value
if (retCode != 0)
{
displayError(retCode, ddpro.ext_err);
return;
}
encryptedData = data.clone(); // A copy of the encrypted data for displaying later
// Initialise the DRIS
ddpro.reset(); // Reset the DRIS fields with random values
ddpro.function = DinkeyPro.DECRYPT_USER_DATA;
ddpro.flags = DinkeyPro.USE_FUNCTION_ARGUMENT; // Java uses DDProtCheck()'s data parameter, so this flag must be set
ddpro.rw_length = data.length;
ddpro.data_crypt_key_num = 1; // This must be the same key used to encrypt the data
// Encrypt the DRIS
ddpro.cryptDris(DRIS_ENCRYPTION_PARAMETER_1, DRIS_ENCRYPTION_PARAMETER_2, DRIS_ENCRYPTION_PARAMETER_3);
// Do not call cryptApiData() here to encrypt the data passed to the API!
// The data is already encrypted, so the API does not expect an unnecessary second layer of encryption
// Call the API
retCode = ddpro.checkProtection(data);
// Decrypt the DRIS
ddpro.cryptDris(DRIS_ENCRYPTION_PARAMETER_1, DRIS_ENCRYPTION_PARAMETER_2, DRIS_ENCRYPTION_PARAMETER_3);
// Check the return value
if (retCode != 0)
{
displayError(retCode, ddpro.ext_err);
return;
}
// If taking data encryption parameters from the R/W algorithm:
// Calculate the R/W algorithm result
// The input variables were initialised to random values when ddpro was created
algAnswer = myRwAlgorithm(ddpro.var_a, ddpro.var_b, ddpro.var_c, ddpro.var_d, ddpro.var_e, ddpro.var_f, ddpro.var_g, ddpro.var_h);
// Use the algorithm result to decrypt the data received from the API
ddpro.cryptApiData(data, algAnswer);
// If using constant data encryption parameters:
// ddpro.cryptApiData(data, DATA_ENCRYPTION_PARAMETER_1, DATA_ENCRYPTION_PARAMETER_2, DATA_ENCRYPTION_PARAMETER_3);
System.out.println("Data encryption successful.");
System.out.println("Original data: " + Arrays.toString(originalData));
System.out.println("Encrypted data: " + Arrays.toString(encryptedData));
System.out.println("Decrypted data: " + Arrays.toString(data));
return;
}
// An example of a simple protection check and displaying information about the current users of a network dongle.
// This feature is supported by Dinkey Pro Net and Dinkey FD Net dongles only.
// queryNetUsers() will only work following a call to checkProtection() that established a connection to DinkeyServer.
static void displayNetUsers()
{
int retCode, maxNetUsersToQuery;
DinkeyPro ddpro = new DinkeyPro(); // Create a DinkeyPro instance. All DRIS fields are initialised to random values
// Initialise the DRIS
ddpro.function = DinkeyPro.PROTECTION_CHECK;
ddpro.flags = DinkeyPro.START_NET_USER;
// Call the API
retCode = ddpro.checkProtection();
// Check the return value
if (retCode != 0)
{
displayError(retCode, ddpro.ext_err);
return;
}
// If you lock your software to multiple dongle models,
// you might want to check that a network dongle was found before trying to get network user information
if ((ddpro.model == DinkeyPro.MODEL_LITE) || (ddpro.model == DinkeyPro.MODEL_PLUS))
{
System.out.println("Local dongle found. No network user information to display.");
return;
}
// Set maxNetUsersToQuery to a sensible value!
// This example requests information about 10 users if there is no limit to the number of users supported by the dongle
if (ddpro.net_users == DinkeyPro.UNLIMITED_NET_USERS)
maxNetUsersToQuery = 10;
else
maxNetUsersToQuery = ddpro.net_users;
// Call the API
retCode = ddpro.queryNetUsers(maxNetUsersToQuery);
// Check the return value
if (retCode != 0)
{
System.out.println("An error occurred getting network user information.");
System.out.println("Error: " + retCode + "\nExtended Error: " + ddpro.queryNetUsersExtErr);
return;
}
System.out.println(ddpro.numNetUsers + " current network users:\n");
for (int i = 0; i < ddpro.num_net_users; i++)
{
System.out.println((i+1) + ") " + ddpro.userNames[i] + " @ " + ddpro.computerNames[i] + " (" + ddpro.ipAddresses[i] + ") using licence '" + ddpro.licenceNames[i] + "'");
}
return;
}
// !!!! This method must match one stored in the dongle for protCheckWithAlg() to work correctly.
// For Lite dongles, use DinkeyLook to see the algorithm pre-programmed into the dongle.
// For Plus and Net dongles, ensure this algorithm matches one you specified in DinkeyAdd when adding protection.
static int myAlgorithm(int a, int b, int c, int d, int e, int f, int g, int h)
{
return a + b + c + d + e + f + g + h;
}
// !!!! This method must match the R/W algorithm stored in the dongle for
// writeDataAreaEnc() and readDataAreaEnc() to work correctly.
static int myRwAlgorithm(int a, int b, int c, int d, int e, int f, int g, int h)
{
return a ^ b ^ c ^ d ^ e ^ f;
}
// An example of error reporting. Displays descriptions for some common error codes.
// IMPORTANT - THE MESSAGES DISPLAYED ARE TO HELP DEVELOPERS IMPLEMENT THE DINKEY PRO/FD API.
// THEY ARE NOT SUITABLE FOR DISPLAYING TO USERS!
static void displayError(int retCode, int extErr)
{
switch (retCode)
{
case 401:
System.out.println("Error! No dongles detected!");
break;
case 403:
System.out.println("Error! The dongle is a different type to the one specified in DinkeyAdd.");
break;
case 404:
System.out.println("Error! The dongle is a different model to those specified in DinkeyAdd.");
break;
case 409:
System.out.println("Error! The dongle has not been programmed by DinkeyAdd.");
break;
case 410:
System.out.println("Error! The dongle has a different product code to the one specified in DinkeyAdd.");
break;
case 411:
System.out.println("Error! This software's licence was not found in the dongle.");
break;
case 413:
System.out.println("Error! This software has not been locked by DinkeyAdd. For guidance please read the DinkeyAdd chapter of the user manual.");
break;
case 417:
System.out.println("Error! One or more of the parameters set in the DRIS is incorrect.\nCheck if you are encrypting the DRIS in your code but did not specify DRIS encryption in DinkeyAdd - or vice versa.");
break;
case 423:
System.out.println("Error! The number of network users has been exceeded.");
break;
case 435:
System.out.println("Error! DinkeyServer has not been detected on the network.");
break;
case 922:
System.out.println("Error! The Software Key has expired.");
break;
default:
System.out.println("An error occurred checking the dongle.\nError: " + retCode + "\nExtended Error: " + extErr);
break;
}
return;
}
}

View File

@@ -0,0 +1,438 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Using Dinkey Pro/FD with Java</title>
<style>
body {
color: black;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 13px;
margin: 25px auto;
max-width: 800px;
}
p, ul, ol, table {
margin-top: 0;
margin-bottom: 15px;
}
ul.contents a {
text-decoration: none;
}
h1,h2,h3,h4,h5,h6 {
margin-top: 25px;
margin-bottom: 15px;
}
h2 {
border-top: 1px solid gray;
}
table {
margin-left: auto;
margin-right: auto;
border-collapse: collapse;
}
th, td {
border: 1px solid black;
padding: 0.5em;
text-align: left;
}
.ui_element
{ /* Use for things like program options and menu items */
color: #008000;
font-style: italic;
}
.filepath
{ /* Use for paths and filenames */
font-family: monospace;
font-size: 13px;
font-weight: bold;
}
.manual
{ /* Use when referring to user manual sections/chapters */
font-style: italic;
}
.alert
{
border: 1px solid black;
padding: 15px 15px 15px 58px;
font-weight: bold;
background-repeat: no-repeat;
background-position: 5px 15px;
margin-bottom: 15px;
}
.important
{
background-color: #FFFDD0;
background-image: url('data:image/png;base64,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');
}
.information
{
background-color: #EBF8FF;
background-image: url('data:image/png;base64,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');
}
.alert > p:last-child, .alert > ul:last-child, .alert > ol:last-child
{
/* Cancel double space at bottom of alert caused by above rule */
margin-bottom: 0;
}
.important .filepath, .information .filepath {
/* Make filepaths stand out in sections that are already bold */
font-weight: normal;
}
div.col_wrapper
{
clear: both;
overflow: hidden;
}
div.two_col
{
width: 50%;
float: left;
}
code {
color: gray;
white-space: nowrap;
}
pre {
padding: 15px;
background-color: #EEEEEE;
}
pre > code { /* Block level code snippets */
white-space: pre; /* Override nowrap used for inline code */
color: inherit;
}
code .comment
{
color: green;
}
code .keyword
{
font-weight: bold;
color: blue;
}
code .string
{
color: #A00000;
}
code .constant
{
font-weight: bold;
}
</style>
</head>
<body>
<h1>Using Dinkey Pro/FD with Java</h1>
<div class="alert information">
<p>
Protection checks in Java are implemented using <span class="filepath">DinkeyPro.class</span> to communicate with the dongle via the appropriate native library
(<span class="filepath">DPJava.dll</span> on 32-bit Windows, <span class="filepath">libDPJava64.so</span> 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.
</p>
</div>
<p>
The <code>DinkeyPro</code> 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 <code>System.loadLibrary()</code> and <code>System.load()</code>,
and how Java uses the system property <code>java.library.path</code> to locate native libraries.
</p>
<p>
The native libraries and the <code>DinkeyPro</code> class are part of the <code>uk.microcosm.dinkeydongle</code> package.
See the documentation for your development environment for details of how to include and reference this package in your project.
<span class="filepath">dinkeydongle.jar</span> provides all of the Java classes in the <code>uk.microcosm.dinkeydongle</code> 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 <strong>not</strong> 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.
</p>
<p>
Do not specify a <em>calling program</em> when locking the native libraries.
The calling program for Java software is the user's JVM, which will be different for different users.
</p>
<p>
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.
</p>
<h2>The DinkeyPro Class</h2>
<p>
Instances of <code>DinkeyPro</code> 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 <code>get...()</code> and <code>set...()</code> 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 <code>long</code> fields in the <code>DinkeyPro</code> class.
</p>
<div class="alert information">
<p>
The <code>header</code> and <code>size</code> DRIS members are set automatically.
You do not need to set these fields in your code.
</p>
<p>
<code>rw_data_ptr</code> is not used in Java. To use an API function that passes data to/from the dongle,
you must use the <code>checkProtection(byte[] data)</code> method and also set the <code>USE_FUNCTION_ARGUMENT</code> flag.
</p>
</div>
<h3>Fields</h3>
<p>
Possible values for the <code>function</code> DRIS field, as documented in the user manual:
</p>
<ul>
<li><code>static final int PROTECTION_CHECK</code></li>
<li><code>static final int EXECUTE_ALGORITHM</code></li>
<li><code>static final int WRITE_DATA_AREA</code></li>
<li><code>static final int READ_DATA_AREA</code></li>
<li><code>static final int ENCRYPT_USER_DATA</code></li>
<li><code>static final int DECRYPT_USER_DATA</code></li>
<li><code>static final int FAST_PRESENCE_CHECK</code></li>
<li><code>static final int STOP_NET_USER</code></li>
</ul>
<p>
Possible values for the <code>flags</code> DRIS field, as documented in the user manual:
</p>
<ul>
<li><code>static final int DEC_ONE_EXEC</code></li>
<li><code>static final int DEC_MANY_EXECS</code></li>
<li><code>static final int START_NET_USER</code></li>
<li><code>static final int USE_FUNCTION_ARGUMENT</code></li>
<li><code>static final int CHECK_LOCAL_FIRST</code></li>
<li><code>static final int CHECK_NETWORK_FIRST</code></li>
<li><code>static final int USE_ALT_LICENCE_NAME</code></li>
<li><code>static final int DONT_SET_MAXDAYS_EXPIRY</code></li>
<li><code>static final int MATCH_DONGLE_NUMBER</code></li>
<li><code>static final int DONT_RETURN_FD_DRIVE</code></li>
</ul>
<p>
Possible values for the <code>type</code> DRIS field, as documented in the user manual:
</p>
<ul>
<li><code>static final int TYPE_PRO</code></li>
<li><code>static final int TYPE_FD</code></li>
</ul>
<p>
Possible values for the <code>model</code> DRIS field, as documented in the user manual:
</p>
<ul>
<li><code>static final int MODEL_LITE</code></li>
<li><code>static final int MODEL_PLUS</code></li>
<li><code>static final int MODEL_NET5</code></li>
<li><code>static final int MODEL_NETU</code></li>
</ul>
<p>
Possible values for the <code>net_users</code> DRIS field, as documented in the user manual:
</p>
<ul>
<li><code>static final int UNLIMITED_NET_USERS</code></li>
</ul>
<p>
Directly accessible DRIS fields, as documented in the user manual:
</p>
<ul>
<li><code>int seed1</code></li>
<li><code>int seed2</code></li>
<li><code>int function</code></li>
<li><code>int flags</code></li>
<li><code>long execs_decrement</code></li>
<li><code>int data_crypt_key_num</code></li>
<li><code>int rw_offset</code></li>
<li><code>int rw_length</code></li>
<li><code>int var_a</code></li>
<li><code>int var_b</code></li>
<li><code>int var_c</code></li>
<li><code>int var_d</code></li>
<li><code>int var_e</code></li>
<li><code>int var_f</code></li>
<li><code>int var_g</code></li>
<li><code>int var_h</code></li>
<li><code>int alg_number</code></li>
<li><code>int ret_code</code></li>
<li><code>int ext_err</code></li>
<li><code>int type</code></li>
<li><code>int model</code></li>
<li><code>int sdsn</code></li>
<li><code>long dongle_number</code></li>
<li><code>int update_number</code></li>
<li><code>long data_area_size</code></li>
<li><code>int max_alg_num</code></li>
<li><code>int execs</code></li>
<li><code>int exp_day</code></li>
<li><code>int exp_month</code></li>
<li><code>int exp_year</code></li>
<li><code>long features</code></li>
<li><code>int net_users</code></li>
<li><code>int alg_answer</code></li>
<li><code>long fd_capacity</code></li>
<li><code>int swkey_type</code></li>
<li><code>int swkey_exp_day</code></li>
<li><code>int swkey_exp_month</code></li>
<li><code>int swkey_exp_year</code></li>
</ul>
<p>
Fields used to access information returned by <code>DDGetNetUserList()</code>:
</p>
<ul>
<li><code>int numNetUsers</code> - the current number of network users when <code>DDGetNetUserList()</code> was called.</li>
<li><code>int queryNetUsersExtErr</code> - contains additional error information if <code>DDGetNetUserList()</code> returns failure.</li>
<li><code>String[] licenceNames</code> - the names of the licences currently used by network users.</li>
<li><code>String[] userNames</code> - the usernames of the current network users.</li>
<li><code>String[] computerNames</code> - the computer names of the current network users.</li>
<li><code>String[] ipAddresses</code> - the IP addresses of the current network users.</li>
</ul>
<p>
The string arrays should be used in combination, i.e. <code>licenceNames[0]</code>, <code>userNames[0]</code>,
<code>computerNames[0]</code> and <code>ipAddresses[0]</code> together describe a single network user.
</p>
<h3>Constructors</h3>
<p>
These constructors can throw any exception thrown by <code>System.loadLibrary()</code> and <code>System.load()</code>.
See the documentation for those methods for details.
</p>
<h4>DinkeyPro()</h4>
<p>
Creates a new DinkeyPro instance and calls <code>System.loadLibrary()</code>
to load the native library using the default filename.
The library must be located in one of the paths specified in the <code>java.library.path</code> system property.
The exact filename is implementation-dependent, but the most common names are:
</p>
<ul>
<li>32-bit Windows - <span class="filepath">DPJava.dll</span></li>
<li>64-bit Windows - <span class="filepath">DPJava64.dll</span></li>
<li>32-bit Linux - <span class="filepath">libDPJava.so</span></li>
<li>64-bit Linux - <span class="filepath">libDPJava64.so</span></li>
<li>64-bit macOS - <span class="filepath">libDPJava64.dylib</span></li>
</ul>
<p>
The members of the instance's internal DRIS are initialised to random values.
</p>
<h4>DinkeyPro(String libName)</h4>
<p>
Creates a new DinkeyPro instance and calls <code>System.loadLibrary(libName)</code> to load the native library.
The library must be located in one of the paths specified in the <code>java.library.path</code> system property.
If <code>System.loadLibrary(libName)</code> fails, it then calls <code>System.load(libName)</code>.
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.
</p>
<p>
The members of the instance's internal DRIS are initialised to random values.
</p>
<h3>Methods</h3>
<h4>int checkProtection()</h4>
<p>
Calls <code>DDProtCheck()</code> in the native library using the internal DRIS.
Returns zero on success, or a value indicating the cause of the error on failure.
</p>
<h4>int checkProtection(byte[] data)</h4>
<p>
Calls <code>DDProtCheck()</code> in the native library using the internal DRIS.
<code>data</code> 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 <code>USE_FUNCTION_ARGUMENT</code> flag.
Returns zero on success, or a value indicating the cause of the error on failure.
</p>
<h4>int queryNetUsers(int maxUsersToQuery)</h4>
<p>
Calls <code>DDGetNetUserList()</code> in the native library.
<code>maxNetUsersToQuery</code> 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 <em>per licence</em> network users option), or all licences in the dongle
(if protected with the <em>per product</em> network users option).
Returns zero on success, or a value indicating the cause of the error on failure.
</p>
<h4>int queryNetUsers(String licenceName, int maxUsersToQuery)</h4>
<p>
Calls <code>DDGetNetUserList()</code> in the native library.
<code>maxNetUsersToQuery</code> 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 <code>licenceName</code>.
Returns zero on success, or a value indicating the cause of the error on failure.
</p>
<h4>void reset()</h4>
<p>
Set all members of the internal DRIS to random values.
</p>
<h4>String getProdCode()</h4>
<p>
Return the <code>prodcode</code> member of the internal DRIS as a Java string.
</p>
<h4>String getFdDrive()</h4>
<p>
Return the <code>fd_drive</code> member of the internal DRIS as a Java string.
</p>
<h4>void setAltLicenceName(String altLicenceName)</h4>
<p>
Assign the value of <code>altLicenceName</code> to the <code>alt_licence_name</code> member of the internal DRIS.
</p>
<h4>void cryptDris(int encryptionParameter1, int encryptionParameter2, int encryptionParameter3)</h4>
<p>
Encrypt/decrypt the internal DRIS.
<code>encryptionParameter1</code>, <code>encryptionParameter2</code> and <code>encryptionParameter3</code>
must match the parameters specified for DRIS encryption in DinkeyAdd.
</p>
<h4>void cryptApiData(byte[] data, int algAnswer)</h4>
<p>
Encrypt/decrypt <code>checkProtection()</code>'s <code>data</code> 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 <code>algAnswer</code> must be the result of an algorithm that matches the R/W algorithm specified there.
</p>
<h4>void cryptApiData(byte[] data, int encryptionParameter1, int encryptionParameter2, int encryptionParameter3)</h4>
<p>
Encrypt/decrypt <code>checkProtection()</code>'s <code>data</code> parameter using constant parameters.
The option to use constant data encryption parameters must be selected in DinkeyAdd when adding protection, and
<code>encryptionParameter1</code>, <code>encryptionParameter2</code> and <code>encryptionParameter3</code>
must match the parameters specified there.
</p>
<h2>Java Example Files</h2>
<ul>
<li><span class="filepath">DPSample.java</span> - various examples of using the <code>DinkeyPro</code> class.</li>
</ul>
<h2>Supported Versions</h2>
<p>
All parts of the <code>uk.microcosm.dinkeydongle</code> package support Java platforms version 5 and newer.
</p>
<h2>Try It Yourself</h2>
<div class="alert important">
<p>
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 <span class="manual">Increasing Your Protection</span> in the user manual for many suggestions on how to
make the best use of the API features.
</p>
</div>
<p>
<span class="filepath">DPSample.java</span> 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 <code>java.library.path</code> system property.
Browse the examples in <span class="filepath">DPSample.java</span> to see how different features can be used.
All the examples follow the same basic pattern:
</p>
<ol>
<li>Create a DinkeyPro instance and set up its internal DRIS with the relevant information.</li>
<li>Call the API.</li>
<li>Use the information returned in the internal DRIS.</li>
</ol>
<p>
Uncomment the calls at the top of the <code>main()</code> method in <span class="filepath">DPSample.java</span>
to enable the examples of different features, then recompile and run DPSample to run the examples.
</p>
<p>
Parts of the sample code marked with <code>!!!!</code> 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.
</p>
</body>
</html>