import dris # code that communicates with the Dinkey Pro/FD runtime extension import sys # so we can load the correct extension dependent on OS & bitness # The sample code contains 10 functions. You will not need to use all these # functions in your code. Just use which ever functions are most appropriate # and customise in your own way. The sample code is just a guide. You should # implement the protection in a stronger way using the techniques described in # the "Increasing your Protection" chapter of the manual. # # If you are using Dinkey Lite then you can only use 4 functions: # ProtCheck, ProtCheckWithAlg, ProtCheckEnc, ProtCheckWithAlgEnc # this file contains 10 protection-check functions. # ProtCheck a standard protection check # ProtCheckWithAlg a protection check & executing an Algorithm # WriteBytes a protection check & write data to the dongle # ReadBytes a protection check & read data from the dongle # EncryptUserData a protection check & encrypting data and then decrypting the data # these functions are the same as the functions listed above but encrypting all parameters passed to our API # ProtCheckEnc a standard protection check # ProtCheckWithAlgEnc a protection check & executing an Algorithm # WriteBytesEnc a protection check & write data to the dongle # ReadBytesEnc a protection check & read data from the dongle # EncryptUserDataEnc a protection check & encrypting data and then decrypting the data MY_SDSN = 10101 # !!!! change this value to be the value of your SDSN (demo = 10101) MY_PRODCODE = "DEMO" # !!!! change this value to be the value of the Product Code in the dongle # ************************* our 10 functions ********************************** # ************************** ProtCheck *************************************** def ProtCheck(): # create the DRIS and allocate the values we want to use mydris = dris.create() dris.set_function(mydris, dris.PROTECTION_CHECK) # standard protection check dris.set_flags(mydris, 0) # no extra flags, but you may want to specify some if you want to start a network user or decrement execs,... ret_code = DDProtCheck(mydris) if (ret_code != 0): dris.DisplayError(ret_code, dris.get_ext_err(mydris)) return # later in your code you can check other values in the DRIS... if (dris.get_sdsn(mydris) != MY_SDSN): print("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.") return if (dris.get_prodcode(mydris) != MY_PRODCODE): print("Incorrect Product Code! Please modify your source code so that MY_PRODCODE is set to be the Product Code in the dongle.") return # later on in your program you can check the return code again if (dris.get_ret_code(mydris) != 0): print("Dinkey Dongle protection error") return print("It worked!") return ret_code # ************************** ProtCheckWithAlg ****************************** # this function should be used instead of % for modulo as python calculates this differently to C for negative numbers def mod(x, y): return abs(x)%abs(y)*(1,-1)[x<0] # this function should be used instead of // for integer division as python calculates this differently to C for negative numbers def div(x, y): if (x >= 0) != (y >= 0) and x % y: return x // y + 1 else: return x // y # !!!! You should replace this function with the one generated by the # "generate source code" button in Algorithm tab for DinkeyAdd (if you have specified an algorithm) # or from DinkeyLook if you are using a Dinkey Lite dongle. # (If it does not generate source code for Python you have translate it from C but use the mod function instead of % and div instead of //) def MyAlgorithm(a, b, c, d, e, f, g, h): value = a + b + c + d + e + f + g + h # place your algorithm here using mod instead of % and div instead of // return dris.make_signed32bit(value) # this line always needs to be here to convert the value to a signed 32bit integer # NB for this to work you must program at least "user algorithm" into the dongle # NB We have used a very simple algorithm here (in the MyAlgorithm function). You must patch this with the # sample code generated by DinkeyAdd for the algorithm that you are using. For Lite models copy the sample # code from DinkeyLook def ProtCheckWithAlg(): # create the DRIS and allocate the values we want to use mydris = dris.create() dris.set_function(mydris, dris.EXECUTE_ALGORITHM) # standard protection check & execute algorithm dris.set_flags(mydris, 0) # no extra flags, but you may want to specify some if you want to start a network user or decrement execs,... dris.set_alg_number(mydris, 1) # execute algorithm 1 (you do not need to specify this field if you are only using Lite models). # you should remove these entries if you are using Dinkey Lite so that algorithm arguments are random dris.set_var_a(mydris, 1) # sample values dris.set_var_b(mydris, 2) dris.set_var_c(mydris, 3) dris.set_var_d(mydris, 4) dris.set_var_e(mydris, 5) dris.set_var_f(mydris, 6) dris.set_var_g(mydris, 7) dris.set_var_h(mydris, 8) ret_code = DDProtCheck(mydris) if (ret_code != 0): dris.DisplayError(ret_code, dris.get_ext_err(mydris)) return # later in your code you can check other values in the DRIS... if (dris.get_sdsn(mydris) != MY_SDSN): print("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.") return # later on in your program you can check the return code again if (dris.get_ret_code(mydris) != 0): print("Dinkey Dongle protection error") return # if you want you can check the algorithm answer - however if algorithm is from your code then best to just use the answer in your code # !!!! Make sure you have replaced the MyAlgorithm routine with the algorithm you have specified in DinkeyAdd if MyAlgorithm(dris.get_var_a(mydris), dris.get_var_b(mydris), dris.get_var_c(mydris), dris.get_var_d(mydris), dris.get_var_e(mydris), \ dris.get_var_f(mydris), dris.get_var_g(mydris), dris.get_var_h(mydris)) != dris.get_alg_answer(mydris): print("Dinkey protection error!\nYou have not patched your algorithm in the MyAlgorithm routine") return print("It worked!") return ret_code # ************************** WriteBytes ****************************** # This writes the string "Hello, World!" to the dongle data area at offset 7 # In order for this function to work you will need to have a data area in your dongle that is at least 21 bytes long. def WriteBytes(): datatowrite = bytearray("Hello, World!", "ascii") # create the DRIS and allocate the values we want to use mydris = dris.create() dris.set_function(mydris, dris.WRITE_DATA_AREA) # standard protection check and write data dris.set_flags(mydris, dris.USE_FUNCTION_ARGUMENT) # we have to do it this way in Python dris.set_rw_offset(mydris, 7) dris.set_rw_length(mydris, len(datatowrite)) ret_code = DDProtCheck(mydris, datatowrite) if (ret_code != 0): dris.DisplayError(ret_code, dris.get_ext_err(mydris)) return # later in your code you can check other values in the DRIS... if (dris.get_sdsn(mydris) != MY_SDSN): print("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.") return # later on in your program you can check the return code again if (dris.get_ret_code(mydris) != 0): print("Dinkey Dongle protection error") return print("It worked!") return ret_code # ************************ ReadBytes ************************************ # This reads 13 bytes of data from offset 7 in the dongle data area # In order for this function to work you will need to have a data area in your dongle that is at least 21 bytes long. # In order for the data to be displayed properly by this routine it will need to be text data def ReadBytes(): datatoread = bytearray(13) # create the DRIS and allocate the values we want to use mydris = dris.create() dris.set_function(mydris, dris.READ_DATA_AREA) # standard protection check and read data dris.set_flags(mydris, dris.USE_FUNCTION_ARGUMENT) # we have to do it this way in Python dris.set_rw_offset(mydris, 7) dris.set_rw_length(mydris, len(datatoread)) ret_code = DDProtCheck(mydris, datatoread) if (ret_code != 0): dris.DisplayError(ret_code, dris.get_ext_err(mydris)) return # later in your code you can check other values in the DRIS... if (dris.get_sdsn(mydris) != MY_SDSN): print("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.") return # later on in your program you can check the return code again if (dris.get_ret_code(mydris) != 0): print("Dinkey Dongle protection error") return print("It worked! Dinkey Dongle Data area, offset 7 is " + datatoread.decode("ascii")) return ret_code # ************************** EncryptUserData **************************** # This function will do a protection check and ask the dongle to encrypt some data using encryption key 1 # It will then do another protection check & decrypt the data def EncryptUserData(): data = bytearray("Hello, World!", "ascii") # create the DRIS and allocate the values we want to use mydris = dris.create() dris.set_function(mydris, dris.ENCRYPT_USER_DATA) # standard protection check and encrypt data dris.set_flags(mydris, dris.USE_FUNCTION_ARGUMENT) # we have to do it this way in Python dris.set_data_crypt_key_num(mydris, 1) dris.set_rw_length(mydris, len(data)) ret_code = DDProtCheck(mydris, data) if (ret_code != 0): dris.DisplayError(ret_code, dris.get_ext_err(mydris)) return # ... could add code to check other elements of the DRIS, e.g. ret_code, sdsn, ... # Now decrypt this (encrypted) data to get the original values mydris2 = dris.create() dris.set_function(mydris2, dris.DECRYPT_USER_DATA) # standard protection check and decrypt data dris.set_flags(mydris2, dris.USE_FUNCTION_ARGUMENT) # we have to do it this way in Python dris.set_data_crypt_key_num(mydris2, 1) dris.set_rw_length(mydris2, len(data)) ret_code = DDProtCheck(mydris2, data) if (ret_code != 0): dris.DisplayError(ret_code, dris.get_ext_err(mydris2)) return # later in your code you can check other values in the DRIS... if (dris.get_sdsn(mydris2) != MY_SDSN): print("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.") return # later on in your program you can check the return code again if (dris.get_ret_code(mydris2) != 0): print("Dinkey Dongle protection error") return print("It worked! Data decrypted is " + data.decode("ascii")) return ret_code # !!!!!!!!!!! all the functions listed below encrypt all parameters to our API !!!!!!!!!!!!!!!!!!!!! # In order for them to work properly you need to choose "Encrypt DRIS" and "Encrypt Data passed to API" # in the Extra Security tab of DinkeyAdd. In this example, for Data Encryption I use the r/w algorithm # but the code can be modified easily to use the 3 encryption parameters. # !!!! please overwrite this function with the one generated by DinkeyAdd for R/W Algorithm # NB DinkeyAdd currently does not generate code for Python so you will have to translate it from C def MyRWAlgorithm(a, b, c, d, e, f, g, h): value = a ^ b ^ c ^ d ^ e ^ f return dris.make_signed32bit(value) # !!!! please overwrite this function with the one generated by DinkeyAdd # It is not generated by DinkeyAdd for Python currently so just modify parameters 1,2 and 3 accordingly def CryptDRIS(mydris): bigseed = bytearray(256) S = bytearray(256) for i in range(0, 256, 8): bigseed[i:i+4] = mydris[8:12] # seed1 bigseed[i+4:i+8] = mydris[12:16] # seed2 for i in range(256): S[i] = i j = 0 for i in range(256): j = (j + S[i] + bigseed[i] + 123) % 256 # !!!! parameter 1 temp = S[i] S[i] = S[j] S[j] = temp i = 0 j = 0 for k in range(16,dris.DRIS_SIZE): i = (i + 1) % 256 j = (j + S[i] + 212) % 256 # !!!! parameter 2 temp = S[i] S[i] = S[j] S[j] = temp t = (S[i] + S[j] + 97) % 256 # !!!! parameter 3 mydris[k] = mydris[k] ^ S[t] return # !!!! please overwrite this function with the one generated by DinkeyAdd # It is not generated by DinkeyAdd for Python currently. This is set-up for using r/w parameters def CryptApiData(data, mydris, length, alg_answer): bigseed = bytearray(256) S = bytearray(256) for i in range(0, 256, 8): bigseed[i:i+4] = mydris[8:12] # seed1 bigseed[i+4:i+8] = mydris[12:16] # seed2 for i in range(256): S[i] = i j = 0 for i in range(256): j = (j + S[i] + bigseed[i] + (alg_answer & 0xff)) % 256 # parameter 1 temp = S[i] S[i] = S[j] S[j] = temp i = 0 j = 0 for k in range(length): i = (i + 1) % 256 j = (j + S[i] + ((alg_answer >> 8) & 0xff)) % 256 # parameter 2 temp = S[i] S[i] = S[j] S[j] = temp t = (S[i] + S[j] + ((alg_answer >> 16) & 0xff)) % 256 # parameter 3 data[k] = data[k] ^ S[t] return # ************************* ProtCheckEnc ******************************* def ProtCheckEnc(): # We encrypt the DRIS passed to the API. Patch the CryptDRIS function in this file from source code generated by DinkeyAdd. mydris = dris.create() dris.set_function(mydris, dris.PROTECTION_CHECK) # standard protection check dris.set_flags(mydris, 0) # no extra flags, but you may want to specify some if you want to start a network user or decrement execs,... CryptDRIS(mydris) # encrypt DRIS (!!!!you should separate from DDProtCheck for greater security) ret_code = DDProtCheck(mydris) CryptDRIS(mydris) # decrypt DRIS (!!!!you should separate from DDProtCheck for greater security) if (ret_code != 0): dris.DisplayError(ret_code, dris.get_ext_err(mydris)) return # later in your code you can check other values in the DRIS... if (dris.get_sdsn(mydris) != MY_SDSN): print("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.") return if (dris.get_prodcode(mydris) != MY_PRODCODE): print("Incorrect Product Code! Please modify your source code so that MY_PRODCODE is set to be the Product Code in the dongle.") return # later on in your program you can check the return code again if (dris.get_ret_code(mydris) != 0): print("Dinkey Dongle protection error") return print("It worked!") return ret_code # ************************ ProtCheckWithAlgEnc *********************** # NB for this to work you must program at least "user algorithm" into the dongle # NB We have used a very simple algorithm here (in the MyAlgorithm function). You must patch this with the # sample code generated by DinkeyAdd for the algorithm that you are using. For Lite models copy the sample # code from DinkeyLook # We encrypt the DRIS passed to the API. Patch the CryptDRIS function in this file from source code generated by DinkeyAdd. def ProtCheckWithAlgEnc(): # create the DRIS and allocate the values we want to use mydris = dris.create() dris.set_function(mydris, dris.EXECUTE_ALGORITHM) # standard protection check & execute algorithm dris.set_flags(mydris, 0) # no extra flags, but you may want to specify some if you want to start a network user or decrement execs,... dris.set_alg_number(mydris, 1) # execute algorithm 1 (you do not need to specify this field if you are only using Lite models). # you should remove these entries if you are using Dinkey Lite so that algorithm arguments are random dris.set_var_a(mydris, 1) # sample values dris.set_var_b(mydris, 2) dris.set_var_c(mydris, 3) dris.set_var_d(mydris, 4) dris.set_var_e(mydris, 5) dris.set_var_f(mydris, 6) dris.set_var_g(mydris, 7) dris.set_var_h(mydris, 8) CryptDRIS(mydris) # encrypt DRIS (!!!!you should separate from DDProtCheck for greater security) ret_code = DDProtCheck(mydris) CryptDRIS(mydris) # decrypt DRIS (!!!!you should separate from DDProtCheck for greater security) if (ret_code != 0): dris.DisplayError(ret_code, dris.get_ext_err(mydris)) return # later in your code you can check other values in the DRIS... if (dris.get_sdsn(mydris) != MY_SDSN): print("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.") return # later on in your program you can check the return code again if (dris.get_ret_code(mydris) != 0): print("Dinkey Dongle protection error") return # if you want you can check the algorithm answer - however if algorithm is from your code then best to just use the answer in your code # !!!! Make sure you have replaced the MyAlgorithm routine with the algorithm you have specified in DinkeyAdd if MyAlgorithm(dris.get_var_a(mydris), dris.get_var_b(mydris), dris.get_var_c(mydris), dris.get_var_d(mydris), dris.get_var_e(mydris), \ dris.get_var_f(mydris), dris.get_var_g(mydris), dris.get_var_h(mydris)) != dris.get_alg_answer(mydris): print("Dinkey protection error!\nYou have not patched your algorithm in the MyAlgorithm routine") return print("It worked!") return ret_code # ************************** WriteBytesEnc ****************************** # This writes the string "Hello, World!" to the dongle data area at offset 7 # In order for this function to work you will need to have a data area in your dongle that is at least 21 bytes long. # We encrypt the DRIS and Data passed to the API. Patch the CryptDRIS and CryptApiData functions in this file from source code generated by DinkeyAdd. def WriteBytesEnc(): datatowrite = bytearray("Hello, World!", "ascii") # create the DRIS and allocate the values we want to use mydris = dris.create() dris.set_function(mydris, dris.WRITE_DATA_AREA) # standard protection check and write data dris.set_flags(mydris, dris.USE_FUNCTION_ARGUMENT) # we have to do it this way in Python dris.set_rw_offset(mydris, 7) dris.set_rw_length(mydris, len(datatowrite)) # calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm alg_ans = MyRWAlgorithm(dris.get_var_a(mydris), dris.get_var_b(mydris), dris.get_var_c(mydris), dris.get_var_d(mydris), \ dris.get_var_e(mydris), dris.get_var_f(mydris), dris.get_var_g(mydris), dris.get_var_h(mydris)) # encrypt data we want to write. CryptApiData(datatowrite, mydris, len(datatowrite), alg_ans) CryptDRIS(mydris) # encrypt DRIS (!!!!you should separate from DDProtCheck for greater security) ret_code = DDProtCheck(mydris, datatowrite) CryptDRIS(mydris) # decrypt DRIS (!!!!you should separate from DDProtCheck for greater security) if (ret_code != 0): dris.DisplayError(ret_code, dris.get_ext_err(mydris)) return # later in your code you can check other values in the DRIS... if (dris.get_sdsn(mydris) != MY_SDSN): print("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.") return # later on in your program you can check the return code again if (dris.get_ret_code(mydris) != 0): print("Dinkey Dongle protection error") return print("It worked!") return ret_code # ************************ ReadBytesEnc ************************************ # This reads 13 bytes of data from offset 7 in the dongle data area # In order for this function to work you will need to have a data area in your dongle that is at least 21 bytes long. # In order for the data to be displayed properly by this routine it will need to be text data # We encrypt the DRIS and Data passed from the API. Patch the CryptDRIS and CryptApiData functions in this file from source code generated by DinkeyAdd. def ReadBytesEnc(): datatoread = bytearray(13) # create the DRIS and allocate the values we want to use mydris = dris.create() dris.set_function(mydris, dris.READ_DATA_AREA) # standard protection check and read data dris.set_flags(mydris, dris.USE_FUNCTION_ARGUMENT) # we have to do it this way in Python dris.set_rw_offset(mydris, 7) dris.set_rw_length(mydris, len(datatoread)) # calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm alg_ans = MyRWAlgorithm(dris.get_var_a(mydris), dris.get_var_b(mydris), dris.get_var_c(mydris), dris.get_var_d(mydris), \ dris.get_var_e(mydris), dris.get_var_f(mydris), dris.get_var_g(mydris), dris.get_var_h(mydris)) CryptDRIS(mydris) # encrypt DRIS (!!!!you should separate from DDProtCheck for greater security) ret_code = DDProtCheck(mydris, datatoread) CryptDRIS(mydris) # decrypt DRIS (!!!!you should separate from DDProtCheck for greater security) if (ret_code != 0): dris.DisplayError(ret_code, dris.get_ext_err(mydris)) return # later in your code you can check other values in the DRIS... if (dris.get_sdsn(mydris) != MY_SDSN): print("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.") return # later on in your program you can check the return code again if (dris.get_ret_code(mydris) != 0): print("Dinkey Dongle protection error") return # decrypt data that was read CryptApiData(datatoread, mydris, len(datatoread), alg_ans) print("It worked! Dinkey Dongle Data area, offset 7 is " + datatoread.decode("ascii")) return ret_code # ************************** EncryptUserDataEnc **************************** # This function will do a protection check and ask the dongle to encrypt some data using encryption key 1 # It will then do another protection check & decrypt the data # We encrypt the DRIS and Data passed to/from the API. Patch the CryptDRIS and CryptApiData functions in this file from source code generated by DinkeyAdd. def EncryptUserDataEnc(): data = bytearray("Hello, World!", "ascii") # create the DRIS and allocate the values we want to use mydris = dris.create() dris.set_function(mydris, dris.ENCRYPT_USER_DATA) # standard protection check and encrypt data dris.set_flags(mydris, dris.USE_FUNCTION_ARGUMENT) # we have to do it this way in Python dris.set_data_crypt_key_num(mydris, 1) dris.set_rw_length(mydris, len(data)) # calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm alg_ans = MyRWAlgorithm(dris.get_var_a(mydris), dris.get_var_b(mydris), dris.get_var_c(mydris), dris.get_var_d(mydris), \ dris.get_var_e(mydris), dris.get_var_f(mydris), dris.get_var_g(mydris), dris.get_var_h(mydris)) # encrypt data we want to pass. CryptApiData(data, mydris, len(data), alg_ans) CryptDRIS(mydris) # encrypt DRIS (!!!!you should separate from DDProtCheck for greater security) ret_code = DDProtCheck(mydris, data) CryptDRIS(mydris) # decrypt DRIS (!!!!you should separate from DDProtCheck for greater security) if (ret_code != 0): dris.DisplayError(ret_code, dris.get_ext_err(mydris)) return # ... could add code to check other elements of the DRIS, e.g. ret_code, sdsn, ... # Now decrypt this (encrypted) data to get the original values mydris2 = dris.create() dris.set_function(mydris2, dris.DECRYPT_USER_DATA) # standard protection check and decrypt data dris.set_flags(mydris2, dris.USE_FUNCTION_ARGUMENT) # we have to do it this way in Python dris.set_data_crypt_key_num(mydris2, 1) dris.set_rw_length(mydris2, len(data)) CryptDRIS(mydris2) # encrypt DRIS (!!!!you should separate from DDProtCheck for greater security) ret_code = DDProtCheck(mydris2, data) CryptDRIS(mydris2) # decrypt DRIS (!!!!you should separate from DDProtCheck for greater security) if (ret_code != 0): dris.DisplayError(ret_code, dris.get_ext_err(mydris2)) return # later in your code you can check other values in the DRIS... if (dris.get_sdsn(mydris2) != MY_SDSN): print("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.") return # later on in your program you can check the return code again if (dris.get_ret_code(mydris2) != 0): print("Dinkey Dongle protection error") return alg_ans = MyRWAlgorithm(dris.get_var_a(mydris2), dris.get_var_b(mydris2), dris.get_var_c(mydris2), dris.get_var_d(mydris2), \ dris.get_var_e(mydris2), dris.get_var_f(mydris2), dris.get_var_g(mydris2), dris.get_var_h(mydris2)) # decrypt data passed to us by the API CryptApiData(data, mydris2, len(data), alg_ans) print("It worked! Data decrypted is " + data.decode("ascii")) return ret_code # entry point if __name__ == "__main__": # load the correct extension dependent on the OS and bitness of Python if sys.platform == 'win32': if sys.maxsize > 2**32: from dpwin64py import DDProtCheck else: from dpwin32py import DDProtCheck elif 'linux' in sys.platform: if sys.maxsize > 2**32: from dplin64py import DDProtCheck else: from dplin32py import DDProtCheck elif sys.platform == 'darwin': if sys.maxsize > 2**32: from dpmac64py import DDProtCheck else: from dpmac32py import DDProtCheck # choose the protection check function of your choice here. We have chosen the basic protection check. ProtCheck()