From d67d3461007a725604d21ebcc3e4167039171c6b Mon Sep 17 00:00:00 2001 From: mht Date: Sun, 20 Apr 2025 18:32:01 +0330 Subject: [PATCH] Initial commit --- CMakeLists.txt | 21 ++++ Ne-code.cpp | 217 ++++++++++++++++++++++++++++++++++++++++++ keya.h | 110 +++++++++++++++++++++ keya_types.h | 47 +++++++++ lib/.idea/.gitignore | 8 ++ lib/.idea/lib.iml | 8 ++ lib/.idea/modules.xml | 8 ++ lib/.idea/vcs.xml | 4 + lib/libkeya.a | Bin 0 -> 17746 bytes lib/libkeyac.a | Bin 0 -> 102010 bytes main.cpp | 148 ++++++++++++++++++++++++++++ setKey.cpp | 213 +++++++++++++++++++++++++++++++++++++++++ 12 files changed, 784 insertions(+) create mode 100755 CMakeLists.txt create mode 100644 Ne-code.cpp create mode 100755 keya.h create mode 100755 keya_types.h create mode 100755 lib/.idea/.gitignore create mode 100755 lib/.idea/lib.iml create mode 100755 lib/.idea/modules.xml create mode 100755 lib/.idea/vcs.xml create mode 100755 lib/libkeya.a create mode 100755 lib/libkeyac.a create mode 100644 main.cpp create mode 100755 setKey.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..b8a779f --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,21 @@ + +cmake_minimum_required(VERSION 2.6) + +project(KeyASample) + +find_library(KEYAC keyac) +find_library(KEYA keya) + +set(cppdongle_sources Ne-code.cpp) + +set(cppdongle_headers ) + +set(KEYA_LIB_DIR ${CMAKE_SOURCE_DIR}/lib/) + + +link_directories(${KEYA_LIB_DIR}) + +add_executable(run-keya2 ${cppdongle_sources} ${cppdongle_headers}) +target_link_libraries(run-keya2 keya keyac pthread) + + diff --git a/Ne-code.cpp b/Ne-code.cpp new file mode 100644 index 0000000..fbe2485 --- /dev/null +++ b/Ne-code.cpp @@ -0,0 +1,217 @@ +// +// Created by mht on 20.04.25. +// +#include +#include +#include +#include +#include +#include +#include "keya.h" + +using namespace std; + +// Helper to pad data to 16 bytes +void pad_data(vector& data) +{ + size_t pad_len = 16 - (data.size() % 16); + if (pad_len < 16) { + data.insert(data.end(), pad_len, 0); // simple zero padding + } +} + +// Read file into vector +vector read_file(const string& filename) +{ + ifstream file(filename, ios::binary); + return vector((istreambuf_iterator(file)), istreambuf_iterator()); +} + +// Write vector into file +void write_file(const string& filename, const vector& data) +{ + ofstream file(filename, ios::binary); + file.write(reinterpret_cast(data.data()), data.size()); +} + +// Encrypt buffer using KeyA +int encrypt_buffer(vector& data, unsigned char* kp, unsigned char* kr, unsigned char* kw) +{ + KeyA keya; + int result = keya.OpenDevice(0); + if (result != 0) return result; + + result = keya.Init(kp, kr, kw, NULL); + if (result != 0) { + keya.CloseDevice(); + return result; + } + + unsigned char temp[16]; + for (size_t i = 0; i < data.size(); i += 16) { + memcpy(temp, &data[i], 16); + result = keya.EncByKV(0, temp, temp); + if (result != 0) { + keya.CloseDevice(); + return result; + } + memcpy(&data[i], temp, 16); + } + + keya.CloseDevice(); + return 0; +} + +// Decrypt buffer using KeyA +int decrypt_buffer(vector& data, unsigned char* kp, unsigned char* kr, unsigned char* kw) +{ + KeyA keya; + int result = keya.OpenDevice(0); + if (result != 0) return result; + + result = keya.Init(kp, kr, kw, NULL); + if (result != 0) { + keya.CloseDevice(); + return result; + } + + unsigned char temp[16]; + for (size_t i = 0; i < data.size(); i += 16) { + memcpy(temp, &data[i], 16); + result = keya.DecByKV(0, temp, temp); + if (result != 0) { + keya.CloseDevice(); + return result; + } + memcpy(&data[i], temp, 16); + } + + keya.CloseDevice(); + return 0; +} + +// Save size as first 8 bytes (uint64_t) of encrypted file +void prepend_size(vector& data, uint64_t size) +{ + vector result(8); + for (int i = 0; i < 8; ++i) { + result[i] = (size >> (i * 8)) & 0xFF; + } + result.insert(result.end(), data.begin(), data.end()); + data = result; +} + +// Extract original size from first 8 bytes +uint64_t extract_size(vector& data) +{ + uint64_t size = 0; + for (int i = 7; i >= 0; --i) { + size = (size << 8) | data[i]; + } + data.erase(data.begin(), data.begin() + 8); + return size; +} + +// Save list of hashes into a text file +void save_hashes_to_file(const vector& hashes, const string& filename) +{ + ofstream file(filename); + for (const auto& hash : hashes) { + file << hash << "\n"; + } +} + +// Read hashes from decrypted data +vector read_hashes_from_memory(const vector& data) +{ + vector hashes; + istringstream iss(string(data.begin(), data.end())); + string line; + while (getline(iss, line)) { + if (!line.empty()) + hashes.push_back(line); + } + return hashes; +} + +// Check if a hash exists in list +bool hash_exists(const string& input_hash, const vector& hashes) +{ + for (const auto& hash : hashes) { + if (hash == input_hash) { + return true; + } + } + return false; +} + +int main() +{ + // Your keys + unsigned char g_Kp[16] = {0x74,0xD8,0xCD,0x0F,0xC6,0x6A,0x09,0x69,0xB1,0x4A,0xC5,0xD1,0xE9,0x7A,0x9D,0x07}; + unsigned char g_Kr[16] = {0xDA,0x58,0x86,0x3C,0xD6,0x65,0xDF,0xE2,0x84,0x04,0xD3,0x4E,0x74,0xEB,0xBD,0x16}; + unsigned char g_Kw[16] = {0xC8,0xA8,0x16,0x3C,0x59,0xEF,0x9C,0xC4,0xC0,0xEC,0x48,0x41,0x4B,0xE5,0x11,0x37}; + + unsigned char* kp = g_Kp; + unsigned char* kr = g_Kr; + unsigned char* kw = g_Kw; + + // Step 1: Save some hashes to file + vector hashes = { + "8d523c784e2f81de923e2fad5960983b735aca25b2490a1cd50d91dc4b166795b27e59f8dfb76ef5120460224cc9ab5d489dc9ae135a732588dd43f71048771c", + "dd590a463303424547f76562fbaeca485c1b95581b7340ecdd02e308166ddcfcac757ed23b11931d23ca46e1b6498fe3c95bf2fd7f760337b41d9e7f4e396678", + "75863d940c8f298c92ccdcfeca6d809d2e5bf67d23c588d2bd62f4b8f86be8a882e30b9b5e524b79e8cf618290b18eec8b621d9c9d73f5300246bd3e15c99561", + "b6d7ec0a2520e2a2ba8f7bb4807b4f3641b80f1062075028600201b1b01e4ac102e078061cd4618f2e847348b118a11be1341a9d3a41fcfc443f92c69c40ffa1", + "4347b58249eea37f74c8a036ca29d6b2a362b9a8743bbd4f99de75c92b46fd876bf98a65041c28c9f10eb548df7645079fe616b00e42711d52135034fe5dbc55", + "a254cc5e08d0d11da6074fccbbc5fbff7a2ce99e6a36f6294f66e271455d3f0663f70864a74ea7d307c0ad7d76fa30694b52dcd9385a8de21b9a708a791d6a8c", + "f9f0ce3eed54de9e057fd66ae17e4b2dccb5b4b6c17e18a278e6628a8a5ac4e357f06c510370e06da2a62241a3200f3d5334102e045c36b5a74954f2ff070a79", + "a1475fdb4b02de84a57f85babc010e5f12281eedea1c75efeac54af7e40c0dfa1659eaa0b106c6aa3a605c7ec442f477d425db24b75c8a818750d9fe06e3727a", + "183d402bb712787f5aa8bf3f0cbe91d3383fdd460edac3db01ea756ae5afe9ca60d8917d749358a012b2b45eaae04ae5fc10fe17aa42409841dc5b475c2794a1", + "a29fc7db04adb89736832cd94dd1fd3fe405e18db670ef3f055e3310dd2f0fc4dd3c4535adcd1ec3fcd16f45a8b814558586bfc67b1d01d664cd51ee1db05c28", + "0092d1a3a78bab2b85abc55d5a851c3c351d0dacd402d77ad57b6d3f08836262bc7dff8b958368cddedd3aa8246ec4919f77c325210cabeadd2dfde5ce8d0412", + "0485a2fd8aceaddfeb45f4072f64637bec8ab5962e088c4f8f0a46196d6b80c1a2924e1d43fa530b2183e5240507115a3db8d49aae9d100195a6ba1eb8f1adcf", + "ec23e51688c082584821a20038510a818c58a0201dbb7ee133d0b11dfc6456a2ad1de4dd944e8083e378af4e58362b5c3ecf3f242493e0cfc1c1cde58e7fc8f1" + + }; + save_hashes_to_file(hashes, "hashes.txt"); + cout << "Hashes saved to 'hashes.txt'." << endl; + + // Step 2: Encrypt the hashes file + vector hash_data = read_file("hashes.txt"); + + uint64_t original_size = hash_data.size(); // Save original size + pad_data(hash_data); // pad to multiple of 16 + + if (encrypt_buffer(hash_data, kp, kr, kw) == 0) { + prepend_size(hash_data, original_size); // Put size in front + write_file("lic.enc", hash_data); + cout << "Encryption successful. Encrypted file saved as 'lic.enc'." << endl; + } else { + cout << "Encryption failed." << endl; + return 1; + } + + // Step 3: Later... Decrypt and check for input hash + vector enc_data = read_file("hashes.enc"); + uint64_t saved_size = extract_size(enc_data); + + if (decrypt_buffer(enc_data, kp, kr, kw) == 0) { + enc_data.resize(saved_size); // trim padding + vector decrypted_hashes = read_hashes_from_memory(enc_data); + + string input_hash; + cout << "Enter a hash to search for: "; + cin >> input_hash; + + if (hash_exists(input_hash, decrypted_hashes)) { + cout << "Hash FOUND in list." << endl; + } else { + cout << "Hash NOT FOUND." << endl; + } + } else { + cout << "Decryption failed." << endl; + return 1; + } + + return 0; +} diff --git a/keya.h b/keya.h new file mode 100755 index 0000000..2d14050 --- /dev/null +++ b/keya.h @@ -0,0 +1,110 @@ +/* + * KeyA.h + * + * Created on: Aug 19, 2008 + * Author: Hedayat Vatankhah , 2008. + */ + +#ifndef KEYA_H_ +#define KEYA_H_ + +#include "keya_types.h" + +/** This can be sent to OpenDevice function to open the next keya device */ +#define KEYA_NEXT_ID(keya) keya.GetKeyAID() + 1 + +class KeyA +{ + public: + KeyA(uint moduleType = _HID_CLASS); + virtual ~KeyA(); + + static uint GetModuleCount(); + static uint EncBlock(const byte *pKey, const byte *pData, byte *pRes); + static uint DecBlock(const byte *pKey, const byte *pData, byte *pRes); + static char *GetErrorText(int lastError, char *perrText, uint buflen); + + uint OpenDevice(int id); + uint CloseDevice(); + int GetKeyAID(); + + uint SetModuleType(uint moduleType); + uint SetKeyAFunctionality(uint keyaFun); + + uint Init(const byte *pKp, const byte *pKr, const byte *pKw, + const byte *pKw2); + uint NetInit(const byte *pKp, const byte *pKr, const byte *pKw, + const byte *pKw2); + uint SetCallBackProc(CallbackProc pAttachCallBack, void *param); + uint SetAttachCallBackProc(PureAttachCallbackProc pAttachCallBack); + uint SetCallBackWithIDProc(CallbackProcWithID callback, + void *param); + void SetCallbackErrorHandlerProc(CallbackErrorHandler handler); + int GetCallbackThreadErrorNumber(); + + uint SetKAB(const byte *pKA, const byte *pKAB); + uint SetKeyAParameters(const byte *pKA, byte *pData); + + uint ChangeKAB(const byte *pKAB, const byte *pNewKAB); + uint WriteAccessKey(const byte *pKBB); + + uint ReadPayamPardazMemory(int address, int len, byte *pBuf); + uint WritePayamPardazMemory(int address, int len, + const byte *pKA, const byte *pData); + + uint ReadFreeMemory(int address, int len, byte *pBuf); + uint WriteFreeMemory(int address, int len, const byte *pBuf); + + uint ReadUserMemory(int address, int len, const byte *pUserKey, + byte *pBuf); + uint WriteUserMemory(int address, int len, const byte *pUserKey, + const byte *pBuf); + uint ReadUserMemory(int address, int len, byte *pBuf); + uint WriteUserMemory(int address, int len, const byte *pBuf); + + uint ReadDeveloperMemory(int address, int len, byte *pBuf); + uint WriteDeveloperMemory(int address, int len, const byte *pBuf); + + uint SetMasterPin(const char *pPin, byte pinLen); + uint SetUserPin(const char *pPin, byte pinLen); + uint UserLogin(const char *pPin, byte pinLen); + uint MasterLogin(const char *pPin, byte pinLen); + //////////////////// New Functions ////////////////// + uint GetAutoLoginStatus(); + uint ResetAutoLogin(); + uint SetAutoLogin(const char *pUserPin, int PinLen, const byte *pAutoLoginKey ); + uint AutoLogin(const byte *pAutoLoginKey ); + uint SetModuleName(const char *strModuleName ); + uint GetModuleName(char *strModuleName, int nModuleNameSize ); + //////////////////////////////////////////////////////////// + uint SetKV(byte iKVIndex, const byte *pKV); + uint EncByKV(byte iKvIndex, const byte *pData, byte *pRes); + uint DecByKV(byte iKvIndex, const byte *pData, byte *pRes); + + uint SetQuery(byte iQueryIndex, const byte *pQueryKey); + uint GetQuery(byte iQueryIndex, const byte *pQueryData, + byte *pQueryResult); + + uint EncByCustomKey(const byte *pCusKey, const byte *pData, + byte *pRes); + uint DecByCustomKey(const byte *pCusKey, const byte *pData, + byte *pRes); + + uint CheckModuleExistence(); + uint GetSerialNumber(byte *pSerialNum); + uint GetMemoryInfo(int *pDevMemLen, int *pSecMemLen, + int *pFMemLen); + uint GetVersionInfo(byte *pVer, byte *pDevMemSup, + byte *pFmemSup, byte *pLoginSup, byte *pCusKeySup); + uint GetKeyCount(int *pQueryKeyNum, int *pKVKeyNum); + + uint SetMaxClient(byte clientNum); + uint GetMaxClient(byte *pClientNum); + + private: + KeyAHID *keya; + + KeyA(KeyA &); +}; + +#endif /* KEYA_H_ */ diff --git a/keya_types.h b/keya_types.h new file mode 100755 index 0000000..31c0326 --- /dev/null +++ b/keya_types.h @@ -0,0 +1,47 @@ +/* + * types.h + * + * Created on: Aug 14, 2008 + * Author: Hedayat Vatankhah , 2008. + */ + +#ifndef KEYA_TYPES_H_ +#define KEYA_TYPES_H_ + +#define FALSE 0 +#define TRUE 1 + +#ifndef NULL +#define NULL 0 +#endif + +/* + * Defining some basic types. (NOTICE: data type collision is possible. fix this! + * Maybe using unsigned instead of uint is much better?! + */ +typedef unsigned char byte; +#ifndef __KERNEL__ +typedef unsigned int uint; +#ifndef __cplusplus +typedef byte bool; +#endif +#endif + +/** This can be sent to OpenDevice function to open the first available KeyA */ +#define KEYA_FIRST_ID 0 + +typedef int (*PureAttachCallbackProc)(void); +typedef int (*CallbackProc)(bool attached, void *param); +typedef int (*CallbackProcWithID)(bool attached, void *param, int keyaid); +typedef void (*CallbackErrorHandler)(int errnum); + +typedef struct KeyA2HIDProtocol KeyAHID; + +/* Only HID class is acceptable by this driver! */ +enum KeyAModuleClass +{ + _CUSTOME_CLASS, + _HID_CLASS +}; + +#endif /* KEYA_TYPES_H_ */ diff --git a/lib/.idea/.gitignore b/lib/.idea/.gitignore new file mode 100755 index 0000000..13566b8 --- /dev/null +++ b/lib/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/lib/.idea/lib.iml b/lib/.idea/lib.iml new file mode 100755 index 0000000..bc2cd87 --- /dev/null +++ b/lib/.idea/lib.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/lib/.idea/modules.xml b/lib/.idea/modules.xml new file mode 100755 index 0000000..b0c4ff6 --- /dev/null +++ b/lib/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/lib/.idea/vcs.xml b/lib/.idea/vcs.xml new file mode 100755 index 0000000..d843f34 --- /dev/null +++ b/lib/.idea/vcs.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/lib/libkeya.a b/lib/libkeya.a new file mode 100755 index 0000000000000000000000000000000000000000..f5278de63d24834a14616e352cb9119252897b2a GIT binary patch literal 17746 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 literal 0 HcmV?d00001 diff --git a/lib/libkeyac.a b/lib/libkeyac.a new file mode 100755 index 0000000000000000000000000000000000000000..92771c7fec3af775f69f7b58d983bf0f4af12b9b GIT binary patch literal 102010 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

5pg{%OG90Q~<1{+_^p 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 literal 0 HcmV?d00001 diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..9908814 --- /dev/null +++ b/main.cpp @@ -0,0 +1,148 @@ +#include +#include +#include +#include +#include "keya.h" + +using namespace std; + +// Helper to pad data to 16 bytes +void pad_data(vector& data) +{ + size_t pad_len = 16 - (data.size() % 16); + if (pad_len < 16) { + data.insert(data.end(), pad_len, 0); // simple zero padding + } +} + +// Read file into vector +vector read_file(const string& filename) +{ + ifstream file(filename, ios::binary); + return vector((istreambuf_iterator(file)), istreambuf_iterator()); +} + +// Write vector into file +void write_file(const string& filename, const vector& data) +{ + ofstream file(filename, ios::binary); + file.write(reinterpret_cast(data.data()), data.size()); +} + +// Encrypt buffer using KeyA +int encrypt_buffer(vector& data, unsigned char* kp, unsigned char* kr, unsigned char* kw) +{ + KeyA keya; + int result = keya.OpenDevice(0); + if (result != 0) return result; + + result = keya.Init(kp, kr, kw, NULL); + if (result != 0) { + keya.CloseDevice(); + return result; + } + + unsigned char temp[16]; + for (size_t i = 0; i < data.size(); i += 16) { + memcpy(temp, &data[i], 16); + result = keya.EncByKV(0, temp, temp); + if (result != 0) { + keya.CloseDevice(); + return result; + } + memcpy(&data[i], temp, 16); + } + + keya.CloseDevice(); + return 0; +} + +// Decrypt buffer using KeyA +int decrypt_buffer(vector& data, unsigned char* kp, unsigned char* kr, unsigned char* kw) +{ + KeyA keya; + int result = keya.OpenDevice(0); + if (result != 0) return result; + + result = keya.Init(kp, kr, kw, NULL); + if (result != 0) { + keya.CloseDevice(); + return result; + } + + unsigned char temp[16]; + for (size_t i = 0; i < data.size(); i += 16) { + memcpy(temp, &data[i], 16); + result = keya.DecByKV(0, temp, temp); + if (result != 0) { + keya.CloseDevice(); + return result; + } + memcpy(&data[i], temp, 16); + } + + keya.CloseDevice(); + return 0; +} + +// Save size as first 8 bytes (uint64_t) of encrypted file +void prepend_size(vector& data, uint64_t size) +{ + vector result(8); + for (int i = 0; i < 8; ++i) { + result[i] = (size >> (i * 8)) & 0xFF; + } + result.insert(result.end(), data.begin(), data.end()); + data = result; +} + +// Extract original size from first 8 bytes +uint64_t extract_size(vector& data) +{ + uint64_t size = 0; + for (int i = 7; i >= 0; --i) { + size = (size << 8) | data[i]; + } + data.erase(data.begin(), data.begin() + 8); + return size; +} + +int main() +{ + // Your keys + unsigned char g_Kp[16] = {0x74,0xD8,0xCD,0x0F,0xC6,0x6A,0x09,0x69,0xB1,0x4A,0xC5,0xD1,0xE9,0x7A,0x9D,0x07}; + unsigned char g_Kr[16] = {0xDA,0x58,0x86,0x3C,0xD6,0x65,0xDF,0xE2,0x84,0x04,0xD3,0x4E,0x74,0xEB,0xBD,0x16}; + unsigned char g_Kw[16] = {0xC8,0xA8,0x16,0x3C,0x59,0xEF,0x9C,0xC4,0xC0,0xEC,0x48,0x41,0x4B,0xE5,0x11,0x37}; + + unsigned char* kp = g_Kp; + unsigned char* kr = g_Kr; + unsigned char* kw = g_Kw; + + // Step 1: Encrypt JSON file + vector json_data = read_file("orig.txt"); + + uint64_t original_size = json_data.size(); // Save original size + pad_data(json_data); // pad to multiple of 16 + + if (encrypt_buffer(json_data, kp, kr, kw) == 0) { + prepend_size(json_data, original_size); // Put size in front + write_file("data.enc", json_data); + cout << "Encryption successful. Encrypted file saved as 'data.enc'." << endl; + } else { + cout << "Encryption failed." << endl; + } + + // Step 2: Decrypt encrypted file + vector enc_data = read_file("hashes.enc"); + uint64_t saved_size = extract_size(enc_data); // remove first 8 bytes, get size + + if (decrypt_buffer(enc_data, kp, kr, kw) == 0) { + enc_data.resize(saved_size); // trim padding + write_file("hash.txt", enc_data); + cout << "Decryption successful. Decrypted file saved as 'data_decrypted.txt'." << endl; + } else { + cout << "Decryption failed." << endl; + } + + return 0; +} diff --git a/setKey.cpp b/setKey.cpp new file mode 100755 index 0000000..6590ecd --- /dev/null +++ b/setKey.cpp @@ -0,0 +1,213 @@ +#include +#include +#include +#include "keya.h" + +using namespace std; + +const int kv_idx = 0; // The kv index used for encryption +const int data_address = 0; // The start address of memory location to place encypted data + +int produce_data(unsigned char **data, size_t *len) +{ + *len = 20; + *data = new unsigned char[*len]; // Some foo size + + strcpy((char *) *data, "000000"); + // Place the keya serial number in front of the data. + // The length of the serial number is 6 bytes length, + // so the length of the data buffer must be at least 6 bytes. + KeyA keya; + int result; + + result = keya.OpenDevice(0); + if (result != 0) + return result; + + // The serial number will be placed in first six byte of data + result = keya.GetSerialNumber(*data); + if (result != 0) + { + keya.CloseDevice(); + return result; + } + + keya.CloseDevice(); + // End of placing the keya serial number + + return 0; +} + +int write_data(unsigned char *data, size_t len, unsigned char *kp, unsigned char *kr, unsigned char *kw) +{ + unsigned char buffer[16]; + unsigned char *pointer = data; + + KeyA keya; + int result; + int count = 0; + + result = keya.OpenDevice(0); + if (result != 0) + return result; + + // Kw2 is not needed here. Kw2 is only needed for writing to developer memory. + result = keya.Init(kp, kr, kw, NULL); + if (result != 0) + { + keya.CloseDevice(); + return result; + } + + // Data encryption with EncByKV() function is done in 16 bytes blocks, + // so data must be padded for length that not dividable by 16. + while (len > 0) + { + memset(buffer, 0, 16); + if (len < 16) + { + memcpy(buffer, pointer, len); + len = 0; + pointer += len; + } + else + { + memcpy(buffer, pointer, 16); + len -= 16; + pointer += 16; + } + result = keya.EncByKV(kv_idx, buffer, buffer); + if (result != 0) + { + keya.CloseDevice(); + return result; + } + result = keya.WriteUserMemory(data_address + count, 16, NULL, buffer); + if (result != 0) + { + keya.CloseDevice(); + return result; + } + count += 16; + } + + keya.CloseDevice(); + return 0; +} + +int read_data(unsigned char *data, int len, unsigned char *kp, unsigned char *kr, unsigned char *kw) +{ + unsigned char buffer[16]; + unsigned char *pointer = data; + + KeyA keya; + int result; + int count = 0; + + result = keya.OpenDevice(0); + if (result != 0) + return result; + + // Kw2 is not needed here. Kw2 is only needed for writing to developer memory. + result = keya.Init(kp, kr, kw, NULL); + if (result != 0) + { + keya.CloseDevice(); + return result; + } + + while (len > 0) + { + result = keya.ReadUserMemory(data_address + count, 16, NULL, buffer); + if (result != 0) + { + keya.CloseDevice(); + return result; + } + result = keya.DecByKV(kv_idx, buffer, buffer); + if (result != 0) + { + keya.CloseDevice(); + return result; + } + if (len < 16) + { + memcpy(pointer, buffer, len); + len = 0; + pointer += len; + } + else + { + memcpy(pointer, buffer, 16); + len -= 16; + pointer += 16; + } + count += 16; + } + + keya.CloseDevice(); + return 0; +} + +int main(int argc, char** argv) +{ + unsigned char buffer[16]; + unsigned char *data = new unsigned char[6]; + + KeyA keya; + int result; + int exist = keya.CheckModuleExistence(); + cout<< "moudle exis " << exist << endl ; + char* a = new char[300]; // Allocates memory for 60 characters +// keya.GetErrorText(keya.CheckModuleExistence(), a ,300); +// cout<<'\n'<< a <<'\n'; + cout<< "\n Module count: "<< keya.GetModuleCount() <<"\n"; + result = keya.OpenDevice(0); + if (result != 0) + return result; + + cout << "\nopen successfully.\n" << endl; + // The serial number will be placed in first six byte of data + result = keya.GetSerialNumber(data); + cout << "\nserial:"<< data<<".\n" << endl; + + char* b = new char[300]; + + unsigned char g_Kp[16] = {0x74,0xD8,0xCD,0x0F,0xC6,0x6A,0x09,0x69,0xB1,0x4A,0xC5,0xD1,0xE9,0x7A,0x9D,0x07}; + unsigned char g_Kr[16] = {0xDA,0x58,0x86,0x3C,0xD6,0x65,0xDF,0xE2,0x84,0x04,0xD3,0x4E,0x74,0xEB,0xBD,0x16}; + unsigned char g_Kw[16] = {0xC8,0xA8,0x16,0x3C,0x59,0xEF,0x9C,0xC4,0xC0,0xEC,0x48,0x41,0x4B,0xE5,0x11,0x37}; + unsigned char g_Kw2[16] = {0x53,0x1C,0x74,0x5B,0xEC,0x9B,0x8E,0x76,0xD8,0x8E,0x28,0x79,0xD9,0x19,0x6D,0x0D}; + + unsigned char* kp = g_Kp; + unsigned char* kr = g_Kr; + unsigned char* kw = g_Kw; + unsigned char* kw2 = g_Kw2; + + int err = keya.Init(kp, kr, kw, kw2); + + std::cout << "err : " << err << std::endl; + keya.GetErrorText(err,b,300); + + std::cout << "err : " << b << std::endl; + + unsigned char idx = '0'; + + + unsigned char *stuff = new unsigned char[16]; + stuff = (unsigned char *) "aaaaaaaaaaaaaaaa"; + unsigned char *enc = new unsigned char[16]; + keya.EncByKV(idx,stuff,enc); + cout<<"encoded is:"<< enc << endl; + + unsigned char *dec = new unsigned char[16]; + keya.DecByKV(idx,enc,dec); + + cout<<"decoded is:"<< dec << endl; + + keya.CloseDevice(); + cout << "Finished successfully." << endl; + + delete[] data; + delete[] a; + return 0; +}