diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000000000000000000000000000000000..778e626b0812674c6b091cc019869531a26f7dd6 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,9 @@ +[submodule "libdap-crypto"] + path = libdap-crypto + url = https://github.com/cellframe/libdap-crypto.git +[submodule "libdap"] + path = libdap + url = https://github.com/cellframe/libdap.git +[submodule "test/libdap-python"] + path = test/libdap-python + url = https://github.com/cellframe/libdap-python.git diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000000000000000000000000000000000..7227c9af5ba74d205a5f05d993287b98e5aecd53 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,38 @@ +sudo: required +language: python +python: + - "3.7-dev" +compiler: gcc +dist: xenial +notifications: + email: false + +before_install: + - git submodule init + - git submodule update + +install: + - sudo apt-get install gcc make + +script: + - sudo service network-manager start + - mkdir build + - cd build + - cmake ../ + - make + - cp ../test/test_b58.py ./ + - cp ../test/test_b64.py ./ + - cp ../test/test_iaes256_cbc.py ./ + - cp ../test/test_oaes.py ./ + - python3.7 test_b58.py + - python3.7 test_b64.py + - python3.7 test_iaes256_cbc.py + - python3.7 test_oaes.py + + +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - network-manager diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..bfceb387b4773c304c1c11d3cdeaa27dedfa33ac --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,41 @@ +project(dap_crypto_python_module C) +cmake_minimum_required(VERSION 2.8) + +set(CMAKE_VERBOSE_MAKEFILE ON) +set(CMAKE_COLOR_MAKEFILE ON) +set(CMAKE_C_STANDARD 11) +set(SUBMODULES_NO_BUILD ON) + +add_subdirectory(libdap) +add_subdirectory(libdap-crypto) + +file(GLOB CRYPTO_SRCS src/*.c) +file(GLOB CRYPTO_HEADERS include/*.h) + +set(Python_ADDITIONAL_VERSIONS 3.7) +find_package (PythonLibs REQUIRED) +#find_package(PkgConfig) +#pkg_check_modules(PC_JSON-C REQUIRED json-c) +include_directories(${PYTHON_INCLUDE_DIR} include/) + +add_library(${PROJECT_NAME} SHARED ${CRYPTO_SRCS} ${CRYPTO_HEADERS}) + +target_link_libraries(${PROJECT_NAME}) + +target_compile_options( + dap_core PRIVATE + "-fpic" +) +target_compile_options( + dap_crypto PRIVATE + "-fpic" +) + + +target_link_libraries(${PROJECT_NAME} dap_core dap_crypto) + +#if(BUILD_DAP_PYTHON_TESTS) +# add_subdirectory(test) +# enable_testing() +#endif() + diff --git a/README.md b/README.md index 89d60a5f84100696a2f8328f6d6534738fb959ca..8220e1450a0c399cd8b1e760b5868390d176a59e 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,20 @@ # libdap-crypto-python libdap-crypto python binding + +[](https://travis-ci.com/cellframe/libdap-crypto-python) + +## Build and Run tests: +``` +mkdir build +cd build +cmake ../ +make +cp ../test/test_b58.py ./ +cp ../test/test_b64.py ./ +cp ../test/test_iaes256_cbc.py ./ +cp ../test/test_oaes.py ./ +python3.7 test_b58.py +python3.7 test_b64.py +python3.7 test_iaes256_cbc.py +python3.7 test_oaes.py +``` diff --git a/include/key_list.h b/include/key_list.h new file mode 100644 index 0000000000000000000000000000000000000000..2159cb9fe6b7d6d50159a19c3586a7b684087357 --- /dev/null +++ b/include/key_list.h @@ -0,0 +1,32 @@ +#ifndef KEY_LIST_H +#define KEY_LIST_H + + +#include "dap_common.h" +#include "dap_enc_key.h" +#include <stdint.h> +#include <string.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#undef LOG_TAG +#define LOG_TAG "key-list" + +typedef struct key_list{ + dap_enc_key_t **keys; + uint8_t lenght; +}key_list_t; + +key_list_t *key_list_init(void); +void key_list_free(key_list_t* list); +uint8_t key_list_add_element(key_list_t *list, dap_enc_key_t* key); +bool key_list_del_element(key_list_t *list, uint8_t key); +dap_enc_key_t *key_list_get_key(key_list_t *list, uint8_t key); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/libdap-crypto-python.h b/include/libdap-crypto-python.h new file mode 100644 index 0000000000000000000000000000000000000000..d08e40119a00b1061d1787c4566849207c02d3b8 --- /dev/null +++ b/include/libdap-crypto-python.h @@ -0,0 +1,73 @@ +#define PY_SSIZE_T_CLEAN +#include <Python.h> +#include "dap_enc.h" +#include "dap_enc_key.h" +#include "dap_common.h" +#include "wrapping_base58.h" +#include "wrapping_base64.h" +#include "wrapping_dap_enc_key.h" +#include "wrapping_dap_enc_iaes.h" +#include "wrapping_dap_enc_oaes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#undef LOG_TAG +#define LOG_TAG "libdap-python-crypto" + +static PyObject *dap_crypto_init(PyObject *self, PyObject *args); + +static PyObject *dap_crypto_deinit(); + +static PyObject *dap_log_it_debug(PyObject *self, PyObject *args); + +static PyObject *dap_log_it_info(PyObject *self, PyObject *args); + +static PyMethodDef DapCryptoMethods[] = { + {"init", dap_crypto_init, METH_VARARGS, "Initialization of the DAP (Deus Applicaions Prototypes) crypto library"}, + {"deinit", dap_crypto_deinit, METH_NOARGS, "Deinitialization of the DAP (Deus Applicaions Prototypes) crypto library"}, + {"encodeBase58", dap_encode_base58_py, METH_VARARGS, "Encrypts information using the base58 algorithm from the DAP crypto library"}, + {"decodeBase58", dap_decode_base58_py, METH_VARARGS, "Dencrypts information using the base58 algorithm from the DAP crypto library"}, + {"encodeBase64", dap_encode_base64_py, METH_VARARGS, "Encrypts information using the base64 algorithm from the DAP crypto library"}, + {"decodeBase64", dap_decode_base64_py, METH_VARARGS, "Dencrypts information using the base64 algorithm from the DAP crypto library"}, + {"logItDebug", dap_log_it_debug, METH_VARARGS, ""}, + {"logItInfo", dap_log_it_info, METH_VARARGS, ""}, + {"newKey", dap_enc_key_new_py, METH_VARARGS, "The function creates a new key, and returns it with PyObject."}, + {"delKey", dap_enc_key_delete_py, METH_VARARGS, ""}, + {"generateNewKey", dap_enc_key_new_generate_py, METH_VARARGS, ""}, + {"getEncSizeKey", dap_enc_key_get_enc_size_py, METH_VARARGS, ""}, + {"getDecSizeKey", dap_enc_key_get_dec_size_py, METH_VARARGS, ""}, + /*IAES256*/ + {"newKeyIAES", dap_enc_iaes_key_new_py, METH_VARARGS, ""}, + {"deleteKeyIAES", dap_enc_iaes_key_delete_py, METH_VARARGS, ""}, + {"generateKeyIAES", dap_enc_iaes_key_generate_py, METH_VARARGS, ""}, + {"encodeSizeIAES256", dap_enc_iaes256_calc_encode_size_py, METH_VARARGS, ""}, + {"decodeSizeIAES256", dap_enc_iaes256_calc_decode_size_py, METH_VARARGS, ""}, + {"encryptIAES256CBCFast", dap_enc_iaes256_cbc_encrypt_fast_py, METH_VARARGS, ""}, + {"decryptIAES256CBCFast", dap_enc_iaes256_cbc_decrypt_fast_py, METH_VARARGS, ""}, + /*OAES*/ + {"newKeyOAES", dap_enc_oaes_key_new_py, METH_VARARGS, ""}, + {"deleteKeyOAES", dap_enc_oaes_key_delete_py, METH_VARARGS, ""}, + {"generateKeyOAES", dap_enc_oaes_key_generate_py, METH_VARARGS, ""}, + {"encodeSizeOAES", dap_enc_oaes_calc_encode_size_py, METH_VARARGS, ""}, + {"decodeSizeOAES", dap_enc_oaes_calc_decode_size_py, METH_VARARGS, ""}, + {"encryptOAESFast", dap_enc_oaes_encrypt_fast_py, METH_VARARGS, ""}, + {"decryptOAESFast", dap_enc_oaes_decrypt_fast_py, METH_VARARGS, ""}, + {NULL, NULL, 0, NULL} +}; + +static struct PyModuleDef dapcryptomodule = { + PyModuleDef_HEAD_INIT, + "libdap_crypto_python_module", /* name of module */ + NULL, /* module documentation, may be NULL */ + -1, /* size of per-interpreter state of the module, + or -1 if the module keeps state in global variables. */ + DapCryptoMethods +}; + +PyMODINIT_FUNC PyInit_libdap_crypto_python_module(void); + +#ifdef __cplusplus +} +#endif diff --git a/include/wrapping_base58.h b/include/wrapping_base58.h new file mode 100644 index 0000000000000000000000000000000000000000..2eb623d0ed84a748e4c72e8eff7f3f916dc260fa --- /dev/null +++ b/include/wrapping_base58.h @@ -0,0 +1,15 @@ +#include "Python.h" +#include "dap_enc_base58.h" +#include "dap_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +PyObject *dap_encode_base58_py(PyObject *self, PyObject *args); + +PyObject *dap_decode_base58_py(PyObject *self, PyObject *args); + +#ifdef __cplusplus +} +#endif diff --git a/include/wrapping_base64.h b/include/wrapping_base64.h new file mode 100644 index 0000000000000000000000000000000000000000..3e3dd8581c335a77ccd7d475d0310aec49ac4697 --- /dev/null +++ b/include/wrapping_base64.h @@ -0,0 +1,15 @@ +#include "Python.h" +#include "dap_enc_base64.h" +#include "dap_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +PyObject *dap_encode_base64_py(PyObject *self, PyObject *args); + +PyObject *dap_decode_base64_py(PyObject *self, PyObject *args); + +#ifdef __cplusplus +} +#endif diff --git a/include/wrapping_dap_enc_iaes.h b/include/wrapping_dap_enc_iaes.h new file mode 100644 index 0000000000000000000000000000000000000000..c2a9f0078c6318e74db0bc6fedc855e95bdc2144 --- /dev/null +++ b/include/wrapping_dap_enc_iaes.h @@ -0,0 +1,32 @@ +#include "Python.h" +#include "dap_enc_iaes.h" +#include "key_list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#undef LOG_TAG +#define LOG_TAG "wrapping-dap-enc-iaes" + +key_list_t *keys_iaes; + +PyObject* dap_enc_iaes_key_new_py(PyObject *self, PyObject *args); + +PyObject* dap_enc_iaes_key_delete_py(PyObject *self, PyObject *args); +PyObject* dap_enc_iaes_key_generate_py(PyObject *self, PyObject *args); + +PyObject* dap_enc_iaes256_calc_decode_size_py(PyObject *self, PyObject *args); +PyObject* dap_enc_iaes256_calc_encode_size_py(PyObject *self, PyObject *args); + +PyObject* dap_enc_iaes256_cbc_decrypt_py(PyObject *self, PyObject *args); //TODO +PyObject* dap_enc_iaes256_cbc_encrypt_py(PyObject *self, PyObject *args); //TODO + +// Writes result ( out ) in already allocated buffer +PyObject* dap_enc_iaes256_cbc_decrypt_fast_py(PyObject *self, PyObject *args); +// if "a_in size mod IAES_BLOCK_SIZE = 0" encryption will be faster +PyObject* dap_enc_iaes256_cbc_encrypt_fast_py(PyObject *self, PyObject *args); + +#ifdef __cplusplus +} +#endif diff --git a/include/wrapping_dap_enc_key.h b/include/wrapping_dap_enc_key.h new file mode 100644 index 0000000000000000000000000000000000000000..b57bd12c5e902e42a36ae901675d4294494c5edd --- /dev/null +++ b/include/wrapping_dap_enc_key.h @@ -0,0 +1,43 @@ +#include "dap_enc_key.h" +#include "Python.h" +#include "dap_common.h" +#include "key_list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#undef LOG_TAG +#define LOG_TAG "wrapping-dap-enc-key" + +key_list_t *keys; + +PyObject* dap_enc_key_get_enc_size_py(PyObject *self, PyObject *args);//dap_enc_key_t * a_key, const size_t buf_in_size); -> size_t +PyObject* dap_enc_key_get_dec_size_py(PyObject *self, PyObject *args);//dap_enc_key_t * a_key, const size_t buf_in_size); -> size_t + + +// allocate memory for key struct +PyObject* dap_enc_key_new_py(PyObject *self, PyObject *args);//dap_enc_key_type_t a_key_type); ->dap_enc_key_t* + + +// default gen key +PyObject *dap_enc_key_new_generate_py(PyObject *self, PyObject *args);//dap_enc_key_type_t key_type, const void *kex_buf, ->dap_enc_key_t* + //size_t kex_size, const void* seed, + //size_t seed_size, size_t key_size); + +// update struct dap_enc_key_t after insert foreign keys +PyObject* dap_enc_key_update_py(PyObject *self, PyObject *args);//dap_enc_key_t *a_key); ->void + +// for asymmetric gen public key +PyObject *dap_enc_gen_pub_key_from_priv_py(PyObject *self, PyObject *args);//struct dap_enc_key *a_key, void **priv_key, size_t *alice_msg_len); ->dap_enc_key_t * + + +PyObject *dap_enc_gen_key_public_size_py(PyObject *self, PyObject *args);//dap_enc_key_t *a_key); ->size_t +PyObject *dap_enc_gen_key_public_py(PyObject *self, PyObject *args);//dap_enc_key_t *a_key, void * a_output); ->int + +PyObject *dap_enc_key_signature_delete_py(PyObject *self, PyObject *args);//dap_enc_key_type_t a_key_type, uint8_t *a_sig_buf); ->void +PyObject *dap_enc_key_delete_py(PyObject *self, PyObject *args);//dap_enc_key_t * a_key); ->void + +#ifdef __cplusplus +} +#endif diff --git a/include/wrapping_dap_enc_oaes.h b/include/wrapping_dap_enc_oaes.h new file mode 100644 index 0000000000000000000000000000000000000000..1498a9297c79fd364aa4cfe58a26cc374c48acf9 --- /dev/null +++ b/include/wrapping_dap_enc_oaes.h @@ -0,0 +1,32 @@ +#include "Python.h" +#include "dap_enc_oaes.h" +#include "key_list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +key_list_t *keys_oaes; + +PyObject *dap_enc_oaes_key_new_py(PyObject *self, PyObject *args);//struct dap_enc_key * a_key); +PyObject *dap_enc_oaes_key_delete_py(PyObject *self, PyObject *args);//struct dap_enc_key *a_key); +PyObject *dap_enc_oaes_key_generate_py(PyObject *self, PyObject *args);//struct dap_enc_key * a_key, const void *kex_buf, + //size_t kex_size, const void * seed, size_t seed_size, size_t key_size); + +PyObject *dap_enc_oaes_calc_decode_size_py(PyObject *self, PyObject *args);//const size_t size_in); +PyObject *dap_enc_oaes_calc_encode_size_py(PyObject *self, PyObject *args);//const size_t size_in); + +PyObject *dap_enc_oaes_decrypt_py(PyObject *self, PyObject *args);//struct dap_enc_key * a_key, const void * a_in, size_t a_in_size, void ** a_out); +PyObject *dap_enc_oaes_encrypt_py(PyObject *self, PyObject *args);//struct dap_enc_key * a_key, const void * a_in, size_t a_in_size, void ** a_out); + +// Writes result ( out ) in already allocated buffer +PyObject *dap_enc_oaes_decrypt_fast_py(PyObject *self, PyObject *args);//struct dap_enc_key * a_key, const void * a_in, + //size_t a_in_size, void * buf_out, size_t buf_out_size); +// Writes result ( out ) in already allocated buffer +PyObject *dap_enc_oaes_encrypt_fast_py(PyObject *self, PyObject *args);//struct dap_enc_key * a_key, const void * a_in, + //size_t a_in_size, void * buf_out, size_t buf_out_size); + + +#ifdef __cplusplus +} +#endif diff --git a/libdap b/libdap new file mode 160000 index 0000000000000000000000000000000000000000..4896ad4eeda5b8d4b3ba92dfe2eb6d4cf34efcc7 --- /dev/null +++ b/libdap @@ -0,0 +1 @@ +Subproject commit 4896ad4eeda5b8d4b3ba92dfe2eb6d4cf34efcc7 diff --git a/libdap-crypto b/libdap-crypto new file mode 160000 index 0000000000000000000000000000000000000000..bcfcef1cd87cc6cfbc7e47887894c0fa3742a218 --- /dev/null +++ b/libdap-crypto @@ -0,0 +1 @@ +Subproject commit bcfcef1cd87cc6cfbc7e47887894c0fa3742a218 diff --git a/src/key_list.c b/src/key_list.c new file mode 100644 index 0000000000000000000000000000000000000000..83e35a9d20f684f4f2c978b7e2862590c2e3c07a --- /dev/null +++ b/src/key_list.c @@ -0,0 +1,57 @@ +#include "key_list.h" + +key_list_t *key_list_init() +{ + key_list_t *keyList = (key_list_t *)malloc(sizeof(key_list_t)); + keyList->lenght = 0; + return keyList; +} + +void key_list_free(key_list_t* list){ + for (int i=0; i < list->lenght;i++){ + free(list->keys[i]); + } + free(list); +} + +uint8_t key_list_add_element(key_list_t *list, dap_enc_key_t* key){ + uint8_t new_len = list->lenght; + new_len++; + dap_enc_key_t **new_keys = calloc(new_len, sizeof(dap_enc_key_t)); + if (list->lenght != 0) { + memcpy(new_keys, list->keys, list->lenght); + free(list->keys); + } + new_keys[new_len - 1] = key; + list->keys = new_keys; + list->lenght = new_len; + return new_len; + +} + +bool key_list_del_element(key_list_t *list, uint8_t key_id){ + if ((list->lenght-1) > 0) { + return false; + } + uint8_t new_len = list->lenght; + new_len--; + dap_enc_key_t **new_keys = calloc(new_len, sizeof(dap_enc_key_t)); + if (list->lenght - 1 == key_id){ + memcpy(new_keys, list->keys, key_id); + } else if (list->lenght > 1 && key_id < list->lenght) { + memcpy(new_keys, list->keys, key_id); + memcpy(new_keys + key_id, list->keys + (key_id + 1), list->lenght); + } + free(list->keys); + list->keys = new_keys; + list->lenght = new_len; + return true; +} + +dap_enc_key_t *key_list_get_key(key_list_t *list, uint8_t key){ + uint8_t index = key - 1; + if (list->lenght < index) { + return NULL; + } + return list->keys[index]; +} diff --git a/src/libdap-crypto-python.c b/src/libdap-crypto-python.c new file mode 100644 index 0000000000000000000000000000000000000000..74303fd76fa03f4806cbf52fcd17f3fc1abfb182 --- /dev/null +++ b/src/libdap-crypto-python.c @@ -0,0 +1,68 @@ +#include "libdap-crypto-python.h" + +static PyObject* dap_crypto_init(PyObject *self, PyObject *args){ + dap_common_init("libdap-crypto","libdap-crypto-python-module.txt"); + if(dap_enc_init()!=0){ + log_it(L_CRITICAL,"Can't init encryption module"); + return PyLong_FromLong(-1); + } + if(dap_enc_key_init()!=0){ + log_it(L_CRITICAL,"Can't init encryption key module"); + return PyLong_FromLong(-2); + } + keys = key_list_init(); + keys_iaes = keys; + keys_oaes = keys; + return PyLong_FromLong(0); +} + +static PyObject* dap_crypto_deinit(){ + dap_enc_key_deinit(); + dap_enc_deinit(); + key_list_free(keys); + return PyLong_FromLong(0); +} + +/* Information */ +static PyObject *dap_log_it_debug(PyObject *self, PyObject *args){ + const char *data; + if (!PyArg_ParseTuple(args,"s", &data)){ + return NULL; + } + log_it(L_DEBUG, data); + return PyLong_FromLong(0); +} + +static PyObject *dap_log_it_info(PyObject *self, PyObject *args){ + return PyLong_FromLong(0); +} +/*==========================================*/ + +PyMODINIT_FUNC PyInit_libdap_crypto_python_module(void){ + return PyModule_Create(&dapcryptomodule); +} + +int main(int argc, char **argv) { + wchar_t *program = Py_DecodeLocale(argv[0], NULL); + if (program == NULL) { + fprintf(stderr, "Fatal error: cannot decode argv[0]\n"); + exit(1); + } + + /* Add a built-in module, before Py_Initialize */ + PyImport_AppendInittab("libdap_crypto_python_module", PyInit_libdap_crypto_python_module); + + /* Pass argv[0] to the Python interpreter */ + Py_SetProgramName(program); + + /* Initialize the Python interpreter. Required. */ + Py_Initialize(); + + /* Optionally import the module; alternatively, + import can be deferred until the embedded script + imports it. */ + PyImport_ImportModule("libdap_crypto_python_module"); + + PyMem_RawFree(program); + return 0; +} diff --git a/src/wrapping_base58.c b/src/wrapping_base58.c new file mode 100644 index 0000000000000000000000000000000000000000..738dd2ce19e7a26f3c48c6c1a364fec989a621dc --- /dev/null +++ b/src/wrapping_base58.c @@ -0,0 +1,24 @@ +#include "wrapping_base58.h" + +PyObject *dap_encode_base58_py(PyObject *self, PyObject *args){ + PyBytesObject *obj; + if (!PyArg_ParseTuple(args, "S", &obj)){ + return NULL; + } + void *in_void = PyBytes_AsString((PyObject*)obj); + size_t pySize = (size_t)PyBytes_GET_SIZE(obj); + char result[DAP_ENC_BASE58_ENCODE_SIZE(pySize)]; + dap_enc_base58_encode(in_void, pySize, result); + return Py_BuildValue("s", result); +} + +PyObject *dap_decode_base58_py(PyObject *self, PyObject *args){ + const char *in_str; + if (!PyArg_ParseTuple(args, "s", &in_str)){ + return NULL; + } + void *res = DAP_NEW_SIZE(void*, DAP_ENC_BASE58_DECODE_SIZE(strlen(in_str))); + size_t decrypted_size = dap_enc_base58_decode(in_str, res); + PyBytesObject *return_object = (PyBytesObject*)PyBytes_FromStringAndSize(res, (Py_ssize_t)decrypted_size); + return Py_BuildValue("O", return_object); +} diff --git a/src/wrapping_base64.c b/src/wrapping_base64.c new file mode 100644 index 0000000000000000000000000000000000000000..aaf19232e27938305a4b6fb882e70d6ab9aef2e3 --- /dev/null +++ b/src/wrapping_base64.c @@ -0,0 +1,33 @@ +#include "wrapping_base64.h" + + PyObject *dap_encode_base64_py(PyObject *self, PyObject *args){ + PyObject *in_data; + short int l_dap_enc_data_type; + if (!PyArg_ParseTuple(args, "S|h", &in_data, &l_dap_enc_data_type)){ + return NULL; + } + if (l_dap_enc_data_type < 1 || l_dap_enc_data_type > 2){ + return NULL; + } + void *in_void = PyBytes_AsString((PyObject*)in_data); + size_t pySize = (size_t)PyBytes_GET_SIZE(in_data); + char result[DAP_ENC_BASE64_ENCODE_SIZE(pySize)]; + dap_enc_base64_encode(in_void, pySize, result, l_dap_enc_data_type); + return Py_BuildValue("s", result); +} + + PyObject *dap_decode_base64_py(PyObject *self, PyObject *args){ + const char *in_str; + short int l_dap_enc_data_type=1; + if (!PyArg_ParseTuple(args, "s|h", &in_str, &l_dap_enc_data_type)) { + return NULL; + } + if (l_dap_enc_data_type < 1 || l_dap_enc_data_type > 2){ + return NULL; + } + void *res = DAP_NEW_SIZE(void*, DAP_ENC_BASE64_ENCODE_SIZE(strlen(in_str))); + //size_t decrypted_size = dap_enc_base58_decode(in_str, res); + size_t decrypted_size = dap_enc_base64_decode(in_str, strlen(in_str), res, l_dap_enc_data_type); + PyBytesObject *return_object = (PyBytesObject*)PyBytes_FromStringAndSize(res, (Py_ssize_t)decrypted_size); + return Py_BuildValue("O", return_object); +} diff --git a/src/wrapping_dap_enc_iaes.c b/src/wrapping_dap_enc_iaes.c new file mode 100644 index 0000000000000000000000000000000000000000..d7cc58017d25faf18175ef2adf49dac3aa4c27d6 --- /dev/null +++ b/src/wrapping_dap_enc_iaes.c @@ -0,0 +1,151 @@ +#include "wrapping_dap_enc_iaes.h" + + +PyObject* dap_enc_iaes_key_new_py(PyObject *self, PyObject *args){ + uint8_t key_id; + if (PyArg_ParseTuple(args, "h", &key_id)){ + return NULL; + } + dap_enc_key_t *key = key_list_get_key(keys_iaes, key_id); + if (key == NULL){ + return NULL; + } + dap_enc_aes_key_new(key); + return PyLong_FromLong(0); +} + +PyObject* dap_enc_iaes_key_delete_py(PyObject *self, PyObject *args){ + uint8_t key_id; + if (PyArg_ParseTuple(args, "h", &key_id)){ + return NULL; + } + dap_enc_key_t *key = key_list_get_key(keys_iaes, key_id); + if (key == NULL){ + return NULL; + } + dap_enc_key_delete(key); + return PyLong_FromLong(0); +} + +PyObject* dap_enc_iaes_key_generate_py(PyObject *self, PyObject *args){ + // TODO + uint8_t in_key_id; + PyBytesObject *in_kex_buf; + size_t in_kex_size; + PyBytesObject *in_seed; + size_t in_seed_size; + if (PyArg_ParseTuple(args, "h|S|n|S|n", &in_key_id, &in_kex_buf, &in_kex_size, &in_seed, &in_seed_size)){ + return NULL; + } + dap_enc_key_t *key = key_list_get_key(keys_iaes, in_key_id); + if (key == NULL){ + return NULL; + } + size_t key_size = sizeof(key); + void* kex_buf = NULL; + PyBytes_AsStringAndSize((PyObject*)in_kex_buf, kex_buf, (Py_ssize_t*)in_kex_size); + void* seed_buf = NULL; + PyBytes_AsStringAndSize((PyObject*)in_seed, seed_buf, (Py_ssize_t*)in_seed_size); + dap_enc_aes_key_generate(key, kex_buf, in_kex_size, seed_buf, in_seed_size, key_size); + return PyLong_FromLong(0); +} + +PyObject* dap_enc_iaes256_calc_encode_size_py(PyObject *self, PyObject *args){ + size_t size; + if (!PyArg_ParseTuple(args, "n", &size)){ + return NULL; + } + size_t new_size = dap_enc_iaes256_calc_encode_size(size); + return PyLong_FromSize_t(new_size); +} + +PyObject* dap_enc_iaes256_calc_decode_size_py(PyObject *self, PyObject *args){ + size_t size; + if (!PyArg_ParseTuple(args, "n", &size)){ + return NULL; + } + size_t new_size = dap_enc_iaes256_calc_decode_size(size); + return PyLong_FromSize_t(new_size); +} + +PyObject* dap_enc_iaes256_cbc_decrypt_py(PyObject *self, PyObject *args){ + //TODO + return PyLong_FromLong(0); + /*uint8_t key_id; + PyBytesObject *in_obj; + size_t in_size; + void **a_out = NULL; + if (!PyArg_ParseTuple(args, "h|S|n", &key_id, &in_obj, &in_size)){ + return NULL; + } + dap_enc_key_t *key = key_list_get_key(keys_iaes, key_id); + if (key == NULL){ + return NULL; + } + //void *in = PyBytes_AsString(in_obj); + void *in_void = PyBytes_AsString((PyObject*)in_obj); + in_size = (size_t)PyBytes_GET_SIZE(in_obj); + dap_enc_iaes256_cbc_decrypt(key, in_void, in_size, a_out); + //TODO + return Py_BuildValue("O", a_out);*/ +} +PyObject* dap_enc_iaes256_cbc_encrypt_py(PyObject *self, PyObject *args){ + //TODO + return PyLong_FromLong(0); + /*uint8_t key_id; + PyBytesObject *in_obj; + size_t in_size; + void **a_out = NULL; + if (!PyArg_ParseTuple(args, "h|S|n", &key_id, &in_obj, &in_size)){ + return NULL; + } + dap_enc_key_t *key = key_list_get_key(keys_iaes, key_id); + if (key == NULL){ + return NULL; + } + void *in_void = PyBytes_AsString((PyObject*)in_obj); + in_size = (size_t)PyBytes_GET_SIZE(in_obj); + dap_enc_iaes256_cbc_encrypt(key, in_void, in_size, a_out); + return PyBytes_FromFormat("%p", a_out);*/ +} + +// Writes result ( out ) in already allocated buffer +PyObject* dap_enc_iaes256_cbc_decrypt_fast_py(PyObject *self, PyObject *args){ + uint8_t key_id; + PyBytesObject *a_in; + size_t a_in_size; + size_t buf_out_size; + if (!PyArg_ParseTuple(args, "h|S|n|n", &key_id, &a_in, &a_in_size, &buf_out_size)){ + return NULL; + } + dap_enc_key_t *key = key_list_get_key(keys_iaes, key_id); + if (key == NULL){ + return NULL; + } + void *in = PyBytes_AsString((PyObject*)a_in); + void *out = DAP_NEW_SIZE(void*, buf_out_size); + size_t res_denc_size = dap_enc_iaes256_cbc_decrypt_fast(key, in, a_in_size, out, buf_out_size); + PyBytesObject *bytes_out = (PyBytesObject*)PyBytes_FromStringAndSize(out, (Py_ssize_t)res_denc_size); + return Py_BuildValue("S", bytes_out); +} + +// if "a_in size mod IAES_BLOCK_SIZE = 0" encryption will be faster +PyObject* dap_enc_iaes256_cbc_encrypt_fast_py(PyObject *self, PyObject *args){ + uint8_t key_id; + PyBytesObject *a_in; + size_t a_in_size; + size_t buf_out_size; + if (!PyArg_ParseTuple(args, "h|S|n|n", &key_id, &a_in, &a_in_size, &buf_out_size)){ + return NULL; + } + dap_enc_key_t *key = key_list_get_key(keys_iaes, key_id); + if (key == NULL){ + return NULL; + } + void *in = PyBytes_AsString((PyObject*)a_in); + void *out = DAP_NEW_SIZE(void*, buf_out_size); + size_t res_enc_size = dap_enc_iaes256_cbc_encrypt_fast(key, in, a_in_size, out, buf_out_size); + PyBytesObject *bytes_out = (PyBytesObject*)PyBytes_FromStringAndSize(out, (Py_ssize_t)res_enc_size); + return Py_BuildValue("S", bytes_out); +} + diff --git a/src/wrapping_dap_enc_key.c b/src/wrapping_dap_enc_key.c new file mode 100644 index 0000000000000000000000000000000000000000..359efebb4bb1bfda3483de3896ed3e5b6863e1f5 --- /dev/null +++ b/src/wrapping_dap_enc_key.c @@ -0,0 +1,148 @@ +#include "wrapping_dap_enc_key.h" + +PyObject* dap_enc_key_get_enc_size_py(PyObject *self, PyObject *args){ + uint8_t key_id; + size_t buff_in_size; + if (!PyArg_ParseTuple(args, "h|i"), &key_id, &buff_in_size){ + return NULL; + } + dap_enc_key_t *key = key_list_get_key(keys, key_id); + if (key == NULL) + return NULL; + size_t size_buff = dap_enc_key_get_enc_size(key, buff_in_size); + if (size_buff == 0) + return NULL; + return PyLong_FromSize_t(size_buff); +} + +PyObject* dap_enc_key_get_dec_size_py(PyObject *self, PyObject *args){ + uint8_t key_id; + size_t buff_in_size; + if (!PyArg_ParseTuple(args, "h|i"), &key_id, &buff_in_size){ + return NULL; + } + dap_enc_key_t *key = key_list_get_key(keys, key_id); + if (key == NULL) + return NULL; + size_t size_buff = dap_enc_key_get_dec_size(key, buff_in_size); + if (size_buff == 0) + return NULL; + return PyLong_FromSize_t(size_buff); +} + +// allocate memory for key struct +PyObject* dap_enc_key_new_py(PyObject *self, PyObject *args){ + uint8_t type_key; + if(!PyArg_ParseTuple(args, "h", &type_key)){ + return NULL; + } + if (type_key > 16){ + return PyLong_FromLong(-1); + } + dap_enc_key_t *new_key = dap_enc_key_new(type_key); + uint8_t res = key_list_add_element(keys, new_key); + return PyLong_FromLong(res); +} + +/// default gen key +PyObject *dap_enc_key_new_generate_py(PyObject *self, PyObject *args){ + uint8_t in_type_key; + PyBytesObject *in_kex_buf; + size_t in_kex_size; + PyBytesObject *in_seed; + size_t in_seed_size; + size_t in_key_size; + if (!PyArg_ParseTuple(args, "h|S|n|S|n|n", &in_type_key, &in_kex_buf, &in_kex_size, &in_seed, + &in_seed_size, &in_key_size)){ + return NULL; + } + if (in_type_key > 16){ + return PyLong_FromLong(-1); + } + void *kex_buf = NULL; + void *seed = NULL; + if (in_kex_size != 0) + kex_buf = PyBytes_AsString((PyObject*)in_kex_buf); + if (in_seed_size != 0) + seed = PyBytes_AsString((PyObject*)in_seed); + dap_enc_key_t *new_key = dap_enc_key_new_generate(in_type_key, kex_buf, in_kex_size, seed, in_seed_size, in_key_size); + uint8_t new_key_id = key_list_add_element(keys, new_key); + return PyLong_FromLong(new_key_id); +} + +// update struct dap_enc_key_t after insert foreign keys +PyObject* dap_enc_key_update_py(PyObject *self, PyObject *args){ + uint8_t key_id; + if (!PyArg_ParseTuple(args, "h", &key_id)){ + return NULL; + } + dap_enc_key_t *key = key_list_get_key(keys, key_id); + if (key == NULL) { + return NULL; + } + dap_enc_key_update(key); + return PyLong_FromLong(0); +} + +// for asymmetric gen public key +PyObject *dap_enc_gen_pub_key_from_priv_py(PyObject *self, PyObject *args){ //NOTE libdap-crypto/src/libdap-crypto.c + return PyLong_FromLong(0); +} + + +PyObject *dap_enc_gen_key_public_size_py(PyObject *self, PyObject *args){ + uint8_t key_id; + if (PyArg_ParseTuple(args, "h", &key_id)){ + return NULL; + } + dap_enc_key_t *key = key_list_get_key(keys, key_id); + if (key == NULL){ + return NULL; + } + size_t size = dap_enc_gen_key_public_size(key); + return PyLong_FromSize_t(size); +} + +PyObject *dap_enc_gen_key_public_py(PyObject *self, PyObject *args){ + uint8_t key_id; + PyObject *obj; + if (PyArg_ParseTuple(args, "h|O", &key_id, &obj)){ + return NULL; + } + dap_enc_key_t *key = key_list_get_key(keys, key_id); + if (key == NULL){ + return NULL; + } + int size = dap_enc_gen_key_public(key, obj); + return PyLong_FromLong(size); +} + +PyObject *dap_enc_key_signature_delete_py(PyObject *self, PyObject *args){ + int type_key; + uint8_t *a_sig_buf; + uint8_t sig_buf; + if(!PyArg_ParseTuple(args, "i|h", &type_key, &sig_buf)){ + return NULL; + } + if (type_key < 0 || type_key > 16){ + return PyLong_FromLong(-1); + } + a_sig_buf = (uint8_t*)sig_buf; + dap_enc_key_signature_delete(type_key, a_sig_buf); + return PyLong_FromLong(0); +} + +PyObject *dap_enc_key_delete_py(PyObject *self, PyObject *args){ + //PyObject *obj; + uint8_t key_id; + if (!PyArg_ParseTuple(args, "h", &key_id)){ + return NULL; + } + dap_enc_key_t *key = key_list_get_key(keys, key_id); + if (key == NULL) { + return NULL; + } + key_list_del_element(keys, key_id); + dap_enc_key_delete(key); + return PyLong_FromLong(0); +} diff --git a/src/wrapping_dap_enc_oaes.c b/src/wrapping_dap_enc_oaes.c new file mode 100644 index 0000000000000000000000000000000000000000..5e2ef99cc1a67edb24013bc01aab03e84e5f04ea --- /dev/null +++ b/src/wrapping_dap_enc_oaes.c @@ -0,0 +1,113 @@ +#include "wrapping_dap_enc_oaes.h" + + +PyObject *dap_enc_oaes_key_new_py(PyObject *self, PyObject *args){ + uint8_t key_id; + if (PyArg_ParseTuple(args, "h", &key_id)){ + return NULL; + } + dap_enc_key_t *key = key_list_get_key(keys_oaes, key_id); + if (key == NULL){ + return NULL; + } + dap_enc_oaes_key_new(key); + return PyLong_FromLong(0); +} +PyObject *dap_enc_oaes_key_delete_py(PyObject *self, PyObject *args){ + uint8_t key_id; + if (PyArg_ParseTuple(args, "h", &key_id)){ + return NULL; + } + dap_enc_key_t *key = key_list_get_key(keys_oaes, key_id); + if (key == NULL){ + return NULL; + } + dap_enc_key_delete(key); + return PyLong_FromLong(0); +} +PyObject *dap_enc_oaes_key_generate_py(PyObject *self, PyObject *args){ + uint8_t in_key_id; + PyBytesObject *in_kex_buf; + size_t in_kex_size; + PyBytesObject *in_seed; + size_t in_seed_size; + if (PyArg_ParseTuple(args, "h|S|n|S|n", &in_key_id, &in_kex_buf, &in_kex_size, &in_seed, &in_seed_size)){ + return NULL; + } + dap_enc_key_t *key = key_list_get_key(keys_oaes, in_key_id); + if (key == NULL){ + return NULL; + } + size_t key_size = sizeof(key); + void* kex_buf = NULL; + PyBytes_AsStringAndSize((PyObject*)in_kex_buf, kex_buf, (Py_ssize_t*)in_kex_size); + void* seed_buf = NULL; + PyBytes_AsStringAndSize((PyObject*)in_seed, seed_buf, (Py_ssize_t*)in_seed_size); + dap_enc_oaes_key_generate(key, kex_buf, in_kex_size, seed_buf, in_seed_size, key_size); + return PyLong_FromLong(0); +} + +PyObject *dap_enc_oaes_calc_decode_size_py(PyObject *self, PyObject *args){ + size_t size; + if (!PyArg_ParseTuple(args, "n", &size)){ + return NULL; + } + size_t new_size = dap_enc_oaes_calc_decode_size(size); + return PyLong_FromSize_t(new_size); +} +PyObject *dap_enc_oaes_calc_encode_size_py(PyObject *self, PyObject *args){ + size_t size; + if (!PyArg_ParseTuple(args, "n", &size)){ + return NULL; + } + size_t new_size = dap_enc_oaes_calc_encode_size(size); + return PyLong_FromSize_t(new_size); +} + +PyObject *dap_enc_oaes_decrypt_py(PyObject *self, PyObject *args){ + //TODO + return PyLong_FromLong(0); +} +PyObject *dap_enc_oaes_encrypt_py(PyObject *self, PyObject *args){ + //TODO + return PyLong_FromLong(0); +} + +// Writes result ( out ) in already allocated buffer +PyObject *dap_enc_oaes_decrypt_fast_py(PyObject *self, PyObject *args){ + uint8_t key_id; + PyBytesObject *a_in; + size_t a_in_size; + size_t buf_out_size; + if (!PyArg_ParseTuple(args, "h|S|n|n", &key_id, &a_in, &a_in_size, &buf_out_size)){ + return NULL; + } + dap_enc_key_t *key = key_list_get_key(keys_oaes, key_id); + if (key == NULL){ + return NULL; + } + void *in = PyBytes_AsString((PyObject*)a_in); + void *out = DAP_NEW_SIZE(void*, buf_out_size); + size_t res_denc_size = dap_enc_oaes_decrypt_fast(key, in, a_in_size, out, buf_out_size); + PyBytesObject *bytes_out = (PyBytesObject*)PyBytes_FromStringAndSize(out, (Py_ssize_t)res_denc_size); + return Py_BuildValue("S", bytes_out); +} +// Writes result ( out ) in already allocated buffer +PyObject *dap_enc_oaes_encrypt_fast_py(PyObject *self, PyObject *args){ + uint8_t key_id; + PyBytesObject *a_in; + size_t a_in_size; + size_t buf_out_size; + if (!PyArg_ParseTuple(args, "h|S|n|n", &key_id, &a_in, &a_in_size, &buf_out_size)){ + return NULL; + } + dap_enc_key_t *key = key_list_get_key(keys_oaes, key_id); + if (key == NULL){ + return NULL; + } + void *in = PyBytes_AsString((PyObject*)a_in); + void *out = DAP_NEW_SIZE(void*, buf_out_size); + size_t res_enc_size = dap_enc_oaes_encrypt_fast(key, in, a_in_size, out, buf_out_size); + PyBytesObject *bytes_out = (PyBytesObject*)PyBytes_FromStringAndSize(out, (Py_ssize_t)res_enc_size); + return Py_BuildValue("S", bytes_out); +} diff --git a/test/dap_enc_key_test.py b/test/dap_enc_key_test.py new file mode 100644 index 0000000000000000000000000000000000000000..17a5476a3bdec1391a1019485f6153519e37fd9b --- /dev/null +++ b/test/dap_enc_key_test.py @@ -0,0 +1,11 @@ +import libdap_crypto_python_module as crypto + +print ("Start dap_enc_key_test") +print ("Crypto init") +crypto.init() +print ("Create KEY") +key = crypto.newKey(1) +print ("Dellete key") +crypto.delKey(key) +print ("Crypto deinit") +crypto.deinit diff --git a/test/libdap-python b/test/libdap-python new file mode 160000 index 0000000000000000000000000000000000000000..e8d7f4e84f0cbca515236f317e9aa5d079df1962 --- /dev/null +++ b/test/libdap-python @@ -0,0 +1 @@ +Subproject commit e8d7f4e84f0cbca515236f317e9aa5d079df1962 diff --git a/test/test.py b/test/test.py new file mode 100644 index 0000000000000000000000000000000000000000..1221f48cbf4145be164c3c99de29930157552820 --- /dev/null +++ b/test/test.py @@ -0,0 +1,21 @@ +import libdap_crypto_python_module as crypto +import unittest + +class TestLibdapCryptoPythonModule(unittest.TestCase): + def test_ini(self): + self.assertTrue(crypto.init() == 0, "Failed init libdap crypto python") + def test_deinit(self): + self.assertTrue(crypto.deinit() == 0, "Failed deinit libdap crypto python") + def test_b58(self): + s = "REvgshguqwt76thuioh1`lwi0-8i-d0hjwpeocnpgh89efty7ug" + crypt = crypto.encodeBase58(s) + decrypt = crypto.decodeBase58(crypt) + self.assertTrue(s == decrypt, "Encoding and decoded information using the base58 algorithm does not match the original") + def test_b64(self): + s = "LindyfekrngFHJFGR23356fer" + crypt = crypto.encodeBase64(bytes(s, "utf-8"), 1) + decrypt = crypto.decodeBase64(crypt, 1) + self.assertTrue(bytes(s, "utf-8") == decrypt, "Encoding and decoded information using the base64 algorithm does not match the original") + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_b58.py b/test/test_b58.py new file mode 100644 index 0000000000000000000000000000000000000000..fbbbf316c59ce20dfa412d32efbd9da8dc65c344 --- /dev/null +++ b/test/test_b58.py @@ -0,0 +1,23 @@ +import libdap_crypto_python_module as crypto +import pickle +import sys + +print ("Start test crypto base58") +s = """Test! I will crush Base58!""" +base_in = pickle.dumps(s) +print ("Input data: "+s) +print (base_in) +crypt = crypto.encodeBase58(base_in) +print ("Encrypted data: \t") +print(crypt) +decrypt = crypto.decodeBase58(crypt) +print ("Decoded data: \t") +print(decrypt) +out_data = pickle.loads(decrypt) +if s == out_data: + print ("TEST 1. Encode/Decode base58 done") +else: + print ("TEST 1. Encode/Decode base58 faild") + sys.exit(1) + +sys.exit(0) diff --git a/test/test_b64.py b/test/test_b64.py new file mode 100644 index 0000000000000000000000000000000000000000..781b6d443ed3a1f1937e319ab16824488c4041eb --- /dev/null +++ b/test/test_b64.py @@ -0,0 +1,30 @@ +import libdap_crypto_python_module as crypto +import sys + +print ("Start test crypto b64") +s = "Test! I will crush Base64!" +print ("Input data: "+s) +crypt = crypto.encodeBase64(bytes(s, "utf-8"),1) +print ("Encrypted data: \t") +print(crypt) +decrypt = crypto.decodeBase64(crypt, 1) +print ("Decoded data: \t") +print(decrypt) +if bytes(s, "utf-8") == decrypt: + print ("TEST 1. Encode/Decode base64 done") +else: + print ("TEST 1. Encode/Decode base64 faild") + sys.exit(1) + +print ("Test Base64 URLSAFE") +u = "http://kelvin.foundation/" +crypt_u = crypto.encodeBase64(bytes(u, "utf-8"), 2) +decrypt_u = crypto.decodeBase64(crypt_u) +if bytes(u, "utf-8") == decrypt_u: + print ("TEST 2. Encode/Decode base64 urlsafe done") +else: + print ("TEST 2. Encode/Decode base64 urlsafe faild") + sys.exit(2) + +sys.exit(0) + diff --git a/test/test_iaes256_cbc.py b/test/test_iaes256_cbc.py new file mode 100644 index 0000000000000000000000000000000000000000..396a7517a912511b8cba1a61ad7619b7644b07c5 --- /dev/null +++ b/test/test_iaes256_cbc.py @@ -0,0 +1,28 @@ +import libdap_crypto_python_module as crypto +import sys + +print ("Start test crypto iaes256 CBC") +s = "Test! I will crush iaes256!" +print ("Input data: "+s) +kex_buff = bytes("123", "utf-8") +size_kex_buff = len(kex_buff) +seed = bytes(112771128) +seed_size = len(seed) +crypto.init() +key_id = crypto.generateNewKey(0, kex_buff, size_kex_buff, seed, seed_size, 0) +print(key_id) +source = bytes(s, "utf-8") +enc = crypto.encryptIAES256CBCFast(key_id, source, len(source), 2048) +decrypt = crypto.decryptIAES256CBCFast(key_id, enc, len(enc), 2048) +print (decrypt) + + +if bytes(s, "utf-8") == decrypt: + print ("TEST 1. Encode/Decode IAES256 CBC FAST done") +else: + print ("TEST 1. Encode/Decode IAES256 CBC FAST faild") + sys.exit(1) + + +sys.exit(0) + diff --git a/test/test_oaes.py b/test/test_oaes.py new file mode 100644 index 0000000000000000000000000000000000000000..7a4d02f67e41c9c4dbcfca77eec7e44d7875894d --- /dev/null +++ b/test/test_oaes.py @@ -0,0 +1,26 @@ +import libdap_crypto_python_module as crypto +import sys + +print ("Start test crypto OAES") +s = "Test! I will crush OAES!" +print ("Input data: "+s) +kex_buff = bytes("114151400014314485131FGXVGHcJFIH", "utf-8") +size_kex_buff = len(kex_buff) +seed = bytes(112771128) +seed_size = len(seed) +crypto.init() +key_id = crypto.generateNewKey(1, kex_buff, size_kex_buff, seed, seed_size, 32) +source = bytes(s, "utf-8") +enc = crypto.encryptOAESFast(key_id, source, len(source), 2048) +decrypt = crypto.decryptOAESFast(key_id, enc, len(enc), 2048) +print (decrypt) + + +if bytes(s, "utf-8") == decrypt: + print ("TEST 1. Encode/Decode OAES FAST done") +else: + print ("TEST 1. Encode/Decode OAES CBC FAST faild") + sys.exit(1) + +sys.exit(0) +