naeural-client 2.3.5__tar.gz → 2.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. {naeural_client-2.3.5 → naeural_client-2.4.0}/PKG-INFO +1 -1
  2. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/_ver.py +1 -1
  3. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/bc/base.py +4 -1
  4. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/bc/ec.py +265 -6
  5. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/const/__init__.py +1 -1
  6. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/const/payload.py +6 -0
  7. {naeural_client-2.3.5 → naeural_client-2.4.0}/pyproject.toml +1 -1
  8. naeural_client-2.4.0/xperimental/enc_dec/enc_dec_test.py +52 -0
  9. naeural_client-2.4.0/xperimental/multi-enc-dec/multi_test1.py +91 -0
  10. naeural_client-2.3.5/xperimental/enc_dec/enc_dec_test.py +0 -74
  11. {naeural_client-2.3.5 → naeural_client-2.4.0}/.devcontainer/Dockerfile +0 -0
  12. {naeural_client-2.3.5 → naeural_client-2.4.0}/.devcontainer/devcontainer.json +0 -0
  13. {naeural_client-2.3.5 → naeural_client-2.4.0}/.gitattributes +0 -0
  14. {naeural_client-2.3.5 → naeural_client-2.4.0}/.github/workflows/python-publish.yml +0 -0
  15. {naeural_client-2.3.5 → naeural_client-2.4.0}/.gitignore +0 -0
  16. {naeural_client-2.3.5 → naeural_client-2.4.0}/.vscode/launch.json +0 -0
  17. {naeural_client-2.3.5 → naeural_client-2.4.0}/LICENSE +0 -0
  18. {naeural_client-2.3.5 → naeural_client-2.4.0}/README.md +0 -0
  19. {naeural_client-2.3.5 → naeural_client-2.4.0}/TODOs.md +0 -0
  20. {naeural_client-2.3.5 → naeural_client-2.4.0}/__init__.py +0 -0
  21. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/__init__.py +0 -0
  22. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/base/__init__.py +0 -0
  23. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/base/distributed_custom_code_presets.py +0 -0
  24. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/base/generic_session.py +0 -0
  25. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/base/instance.py +0 -0
  26. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/base/payload/__init__.py +0 -0
  27. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/base/payload/payload.py +0 -0
  28. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/base/pipeline.py +0 -0
  29. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/base/plugin_template.py +0 -0
  30. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/base/responses.py +0 -0
  31. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/base/transaction.py +0 -0
  32. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/base_decentra_object.py +0 -0
  33. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/bc/__init__.py +0 -0
  34. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/bc/chain.py +0 -0
  35. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/certs/__init__.py +0 -0
  36. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/certs/r9092118.ala.eu-central-1.emqxsl.com.crt +0 -0
  37. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/cli/README.md +0 -0
  38. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/cli/cli.py +0 -0
  39. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/cli/cli_commands.py +0 -0
  40. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/cli/nodes.py +0 -0
  41. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/code_cheker/__init__.py +0 -0
  42. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/code_cheker/base.py +0 -0
  43. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/code_cheker/checker.py +0 -0
  44. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/comm/__init__.py +0 -0
  45. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/comm/amqp_wrapper.py +0 -0
  46. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/comm/mqtt_wrapper.py +0 -0
  47. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/const/README.md +0 -0
  48. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/const/apps.py +0 -0
  49. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/const/base.py +0 -0
  50. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/const/comms.py +0 -0
  51. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/const/environment.py +0 -0
  52. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/const/formatter.py +0 -0
  53. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/const/heartbeat.py +0 -0
  54. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/const/misc.py +0 -0
  55. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/default/__init__.py +0 -0
  56. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/default/instance/__init__.py +0 -0
  57. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/default/instance/chain_dist_custom_job_01_plugin.py +0 -0
  58. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/default/instance/custom_web_app_01_plugin.py +0 -0
  59. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/default/instance/net_mon_01_plugin.py +0 -0
  60. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/default/instance/telegram_basic_bot_01_plugin.py +0 -0
  61. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/default/instance/telegram_conversational_bot_01_plugin.py +0 -0
  62. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/default/instance/view_scene_01_plugin.py +0 -0
  63. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/default/session/mqtt_session.py +0 -0
  64. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/io_formatter/__init__.py +0 -0
  65. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/io_formatter/base/__init__.py +0 -0
  66. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/io_formatter/base/base_formatter.py +0 -0
  67. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/io_formatter/default/__init__.py +0 -0
  68. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/io_formatter/default/a_dummy.py +0 -0
  69. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/io_formatter/default/aixp1.py +0 -0
  70. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/io_formatter/default/default.py +0 -0
  71. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/io_formatter/io_formatter_manager.py +0 -0
  72. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/logging/__init__.py +0 -0
  73. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/logging/base_logger.py +0 -0
  74. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/logging/logger_mixins/__init__.py +0 -0
  75. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/logging/logger_mixins/class_instance_mixin.py +0 -0
  76. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/logging/logger_mixins/computer_vision_mixin.py +0 -0
  77. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/logging/logger_mixins/datetime_mixin.py +0 -0
  78. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/logging/logger_mixins/download_mixin.py +0 -0
  79. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/logging/logger_mixins/general_serialization_mixin.py +0 -0
  80. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/logging/logger_mixins/json_serialization_mixin.py +0 -0
  81. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/logging/logger_mixins/pickle_serialization_mixin.py +0 -0
  82. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/logging/logger_mixins/process_mixin.py +0 -0
  83. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/logging/logger_mixins/resource_size_mixin.py +0 -0
  84. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/logging/logger_mixins/timers_mixin.py +0 -0
  85. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/logging/logger_mixins/upload_mixin.py +0 -0
  86. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/logging/logger_mixins/utils_mixin.py +0 -0
  87. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/logging/small_logger.py +0 -0
  88. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/logging/tzlocal/__init__.py +0 -0
  89. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/logging/tzlocal/unix.py +0 -0
  90. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/logging/tzlocal/utils.py +0 -0
  91. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/logging/tzlocal/win32.py +0 -0
  92. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/logging/tzlocal/windows_tz.py +0 -0
  93. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/plugins_manager_mixin.py +0 -0
  94. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/utils/__init__.py +0 -0
  95. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/utils/comm_utils.py +0 -0
  96. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/utils/config.py +0 -0
  97. {naeural_client-2.3.5 → naeural_client-2.4.0}/naeural_client/utils/dotenv.py +0 -0
  98. {naeural_client-2.3.5 → naeural_client-2.4.0}/requirements.txt +0 -0
  99. {naeural_client-2.3.5 → naeural_client-2.4.0}/tutorials/.example_env +0 -0
  100. {naeural_client-2.3.5 → naeural_client-2.4.0}/tutorials/8. custom_code_fastapi_assets/index.html +0 -0
  101. {naeural_client-2.3.5 → naeural_client-2.4.0}/tutorials/9. code_sandbox_from_scratch_assets/index.html +0 -0
  102. {naeural_client-2.3.5 → naeural_client-2.4.0}/tutorials/_example_pk_sdk.pem +0 -0
  103. {naeural_client-2.3.5 → naeural_client-2.4.0}/tutorials/ex01_part1_connect.py +0 -0
  104. {naeural_client-2.3.5 → naeural_client-2.4.0}/tutorials/ex01_part2_filter.py +0 -0
  105. {naeural_client-2.3.5 → naeural_client-2.4.0}/tutorials/ex02_first_deploy.py +0 -0
  106. {naeural_client-2.3.5 → naeural_client-2.4.0}/tutorials/ex03_custom_code_on_one_remote__example_1.py +0 -0
  107. {naeural_client-2.3.5 → naeural_client-2.4.0}/tutorials/ex04_custom_code_on_one_remote__example_2.py +0 -0
  108. {naeural_client-2.3.5 → naeural_client-2.4.0}/tutorials/ex05_custom_code_on_one_remote__example_3.py +0 -0
  109. {naeural_client-2.3.5 → naeural_client-2.4.0}/tutorials/ex06_custom_code_on_multiple_remotes__example_1.py +0 -0
  110. {naeural_client-2.3.5 → naeural_client-2.4.0}/tutorials/ex07_custom_code_on_multiple_remotes__example_2.py +0 -0
  111. {naeural_client-2.3.5 → naeural_client-2.4.0}/tutorials/ex08_custom_web_app.py +0 -0
  112. {naeural_client-2.3.5 → naeural_client-2.4.0}/tutorials/ex09_code_sandbox_from_scratch.py +0 -0
  113. {naeural_client-2.3.5 → naeural_client-2.4.0}/tutorials/ex10_telegram_echo_bot.py +0 -0
  114. {naeural_client-2.3.5 → naeural_client-2.4.0}/tutorials/ex11_telegram_blackjack_bot.py +0 -0
  115. {naeural_client-2.3.5 → naeural_client-2.4.0}/tutorials/ex12_telegram_smart_bot.py +0 -0
  116. {naeural_client-2.3.5 → naeural_client-2.4.0}/tutorials/video_presentation/1. hello_world.ipynb +0 -0
  117. {naeural_client-2.3.5 → naeural_client-2.4.0}/winrun.bat +0 -0
  118. {naeural_client-2.3.5 → naeural_client-2.4.0}/xperimental/.example_env +0 -0
  119. {naeural_client-2.3.5 → naeural_client-2.4.0}/xperimental/_archive/test.py +0 -0
  120. {naeural_client-2.3.5 → naeural_client-2.4.0}/xperimental/_tutorials/3. simple_real_time_custom_code.py +0 -0
  121. {naeural_client-2.3.5 → naeural_client-2.4.0}/xperimental/_tutorials/4. real_time_custom_code_2.py +0 -0
  122. {naeural_client-2.3.5 → naeural_client-2.4.0}/xperimental/_tutorials/8. chatbot.py +0 -0
  123. {naeural_client-2.3.5 → naeural_client-2.4.0}/xperimental/decentralized/chain_dist_example.py +0 -0
  124. {naeural_client-2.3.5 → naeural_client-2.4.0}/xperimental/decentralized/chain_dist_example_initiator.py +0 -0
  125. {naeural_client-2.3.5 → naeural_client-2.4.0}/xperimental/decentralized/chain_dist_example_worker.py +0 -0
  126. {naeural_client-2.3.5 → naeural_client-2.4.0}/xperimental/eth/eth_sign.py +0 -0
  127. {naeural_client-2.3.5 → naeural_client-2.4.0}/xperimental/eth/info.md +0 -0
  128. {naeural_client-2.3.5 → naeural_client-2.4.0}/xperimental/eth/sign.py +0 -0
  129. {naeural_client-2.3.5 → naeural_client-2.4.0}/xperimental/utils/get_documentation.py +0 -0
  130. {naeural_client-2.3.5 → naeural_client-2.4.0}/xperimental/various/README.md +0 -0
  131. {naeural_client-2.3.5 → naeural_client-2.4.0}/xperimental/various/attach_example.py +0 -0
  132. {naeural_client-2.3.5 → naeural_client-2.4.0}/xperimental/various/ex1.py +0 -0
  133. {naeural_client-2.3.5 → naeural_client-2.4.0}/xperimental/various/hello.py +0 -0
  134. {naeural_client-2.3.5 → naeural_client-2.4.0}/xperimental/various/remote_exec.py +0 -0
  135. {naeural_client-2.3.5 → naeural_client-2.4.0}/xperimental/various/save_images.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: naeural_client
3
- Version: 2.3.5
3
+ Version: 2.4.0
4
4
  Summary: `naeural_client` is the Python SDK required for client app development for the Naeural Edge Protocol Edge Protocol framework
5
5
  Project-URL: Homepage, https://github.com/NaeuralEdgeProtocol/naeural_client
6
6
  Project-URL: Bug Tracker, https://github.com/NaeuralEdgeProtocol/naeural_client/issues
@@ -1,4 +1,4 @@
1
- __VER__ = "2.3.5"
1
+ __VER__ = "2.4.0"
2
2
 
3
3
  if __name__ == "__main__":
4
4
  with open("pyproject.toml", "rt") as fd:
@@ -344,7 +344,10 @@ class BaseBlockEngine:
344
344
  boxed=boxed,
345
345
  **kwargs
346
346
  )
347
-
347
+
348
+ @property
349
+ def name(self):
350
+ return self.__name
348
351
 
349
352
  def _init(self):
350
353
  self.P("Initializing Blockchain engine manager...", boxed=True, box_char='*', verbosity=1)
@@ -3,6 +3,7 @@ import hashlib
3
3
  import os
4
4
  import binascii
5
5
  import zlib
6
+ import json
6
7
 
7
8
  from cryptography.hazmat.primitives import hashes
8
9
  from cryptography.hazmat.primitives.asymmetric import ec
@@ -273,16 +274,16 @@ class BaseBCEllipticCurveEngine(BaseBlockEngine):
273
274
  if debug:
274
275
  print('derived-shared_key: ', base64.b64encode(derived_key))
275
276
  return derived_key
276
-
277
277
 
278
- def encrypt(
278
+
279
+ def _encrypt(
279
280
  self,
280
281
  plaintext: str,
281
282
  receiver_address: str,
282
- compressed: bool = True,
283
- embed_compressed: bool = True,
283
+ compressed: bool = True, # compressed is always True
284
+ embed_compressed: bool = True, # embed_compressed is always True
284
285
  info: str = BCct.DEFAULT_INFO,
285
- debug: bool = False
286
+ debug: bool = False,
286
287
  ):
287
288
  """
288
289
  Encrypts plaintext using the sender's private key and receiver's public key,
@@ -307,6 +308,7 @@ class BaseBCEllipticCurveEngine(BaseBlockEngine):
307
308
  str
308
309
  The base64 encoded nonce and ciphertext.
309
310
  """
311
+
310
312
  if compressed:
311
313
  to_encrypt_data = zlib.compress(plaintext.encode())
312
314
  compressed_flag = (1).to_bytes(1, byteorder='big')
@@ -325,8 +327,51 @@ class BaseBCEllipticCurveEngine(BaseBlockEngine):
325
327
  encrypted_data = nonce + ciphertext # Prepend the nonce to the ciphertext
326
328
  #end if
327
329
  return base64.b64encode(encrypted_data).decode() # Encode to base64
330
+
331
+
332
+ def encrypt(
333
+ self,
334
+ plaintext: str,
335
+ receiver_address: str,
336
+ info: str = BCct.DEFAULT_INFO,
337
+ debug: bool = False,
338
+ **kwargs
339
+ ):
340
+ """
341
+ Encrypts plaintext using the sender's private key and receiver's public key,
342
+ then base64 encodes the output.
343
+
344
+ Parameters
345
+ ----------
346
+ receiver_address : str
347
+ The receiver's address
348
+
349
+ plaintext : str
350
+ The plaintext to encrypt.
351
+
352
+ Obsolete:
353
+ compressed : bool, optional
354
+ Whether to compress the plaintext before encryption. The default is True.
355
+
356
+ embed_compressed : bool, optional
357
+ Whether to embed the compressed flag in the encrypted data. The default is True.
328
358
 
329
- def decrypt(
359
+ Returns
360
+ -------
361
+ str
362
+ The base64 encoded nonce and ciphertext.
363
+ """
364
+ return self._encrypt(
365
+ plaintext=plaintext,
366
+ receiver_address=receiver_address,
367
+ compressed=True,
368
+ embed_compressed=True,
369
+ info=info,
370
+ debug=debug,
371
+ )
372
+
373
+
374
+ def _decrypt(
330
375
  self,
331
376
  encrypted_data_b64 : str,
332
377
  sender_address : str,
@@ -395,6 +440,220 @@ class BaseBCEllipticCurveEngine(BaseBlockEngine):
395
440
  result = None
396
441
  return result
397
442
 
443
+
444
+ ## Multi destination encryption
445
+ def encrypt_for_multi(
446
+ self,
447
+ plaintext: str,
448
+ receiver_addresses: list,
449
+ info: str = BCct.DEFAULT_INFO,
450
+ debug: bool = False
451
+ ):
452
+ """
453
+ Encrypts plaintext for multiple receivers.
454
+
455
+ The overall approach is to encrypt the plaintext with a symmetric key,
456
+ then encrypt the symmetric key with the public key of each receiver.
457
+
458
+ Parameters
459
+ ----------
460
+ plaintext : str
461
+ The plaintext to encrypt.
462
+
463
+ receiver_addresses : list
464
+ List of receiver addresses.
465
+
466
+ Returns
467
+ -------
468
+ str
469
+ The base64 encoded encrypted package.
470
+ """
471
+ to_encrypt_data = zlib.compress(plaintext.encode())
472
+ compressed_flag = (1).to_bytes(1, byteorder='big')
473
+
474
+ # Generate a random symmetric key
475
+ symmetric_key = os.urandom(32) # 256-bit key
476
+
477
+ # Encrypt the plaintext with the symmetric key
478
+ nonce = os.urandom(12)
479
+ aesgcm = AESGCM(symmetric_key)
480
+ ciphertext = aesgcm.encrypt(nonce, to_encrypt_data, None)
481
+
482
+ # For each receiver, encrypt the symmetric key
483
+ encrypted_keys = []
484
+ for receiver_address in receiver_addresses:
485
+ receiver_pk = self._address_to_pk(receiver_address)
486
+ shared_key = self.__derive_shared_key(receiver_pk, info=info, debug=debug)
487
+ # Use shared_key to encrypt the symmetric key
488
+ aesgcm_shared = AESGCM(shared_key)
489
+ nonce_shared = os.urandom(12)
490
+ encrypted_symmetric_key = aesgcm_shared.encrypt(nonce_shared, symmetric_key, None)
491
+ full_enc_key = nonce_shared + encrypted_symmetric_key
492
+ encrypted_keys.append({
493
+ 'a': receiver_address, # Address of the receiver
494
+ 'k': full_enc_key.hex() # Encrypted symmetric key
495
+ })
496
+
497
+ # Package the encrypted symmetric keys and the ciphertext
498
+ encrypted_package = {
499
+ 'M': True, # Multi-recipient flag
500
+ 'c': compressed_flag.hex(), # Compressed flag
501
+ 'n': nonce.hex(), # Nonce
502
+ 'd': ciphertext.hex(), # Ciphertext
503
+ 'k': encrypted_keys # Encrypted symmetric keys
504
+ }
505
+
506
+ # Convert to JSON, compress, and base64 encode
507
+ enc_data = json.dumps(encrypted_package)
508
+ enc_data_compressed = zlib.compress(enc_data.encode())
509
+ enc_data_compressed_b64 = base64.b64encode(enc_data_compressed).decode()
510
+ return enc_data_compressed_b64
511
+
512
+
513
+ def decrypt_for_multi(
514
+ self,
515
+ encrypted_data_b64: str,
516
+ sender_address: str,
517
+ info: str = BCct.DEFAULT_INFO,
518
+ debug: bool = False
519
+ ):
520
+ """
521
+ Decrypts data encrypted for multiple receivers.
522
+
523
+ Parameters
524
+ ----------
525
+ encrypted_data_b64 : str
526
+ The base64 encoded encrypted package as produced by encrypt_for_multi.
527
+
528
+ sender_address : str
529
+ The sender's address (public key address) used to derive the shared key.
530
+
531
+ info : str, optional
532
+ Additional info used in the HKDF for shared key derivation.
533
+
534
+ debug : bool, optional
535
+ If True, prints debug information.
536
+
537
+ Returns
538
+ -------
539
+ str or None
540
+ The decrypted plaintext as a string, or None if decryption fails.
541
+ """
542
+ try:
543
+ # 1. Base64 decode
544
+ enc_data_compressed = base64.b64decode(encrypted_data_b64)
545
+
546
+ # 2. Decompress the JSON structure
547
+ enc_data_json = zlib.decompress(enc_data_compressed).decode()
548
+
549
+ # 3. Parse JSON
550
+ encrypted_package = json.loads(enc_data_json)
551
+
552
+ # Expecting keys: 'M', 'c', 'n', 'd', 'k'
553
+ # 'M' = True indicates multi-recipient
554
+ if 'M' not in encrypted_package or encrypted_package['M'] != True:
555
+ if debug:
556
+ self.P("Not a multi-recipient package.", color='y')
557
+ return None
558
+
559
+ # 'c' = compressed flag (hex)
560
+ compressed_flag_hex = encrypted_package['c']
561
+ compressed_flag = int(compressed_flag_hex, 16)
562
+
563
+ # 'n' = nonce (hex)
564
+ nonce = bytes.fromhex(encrypted_package['n'])
565
+
566
+ # 'd' = ciphertext (hex)
567
+ ciphertext = bytes.fromhex(encrypted_package['d'])
568
+
569
+ # 'k' = list of encrypted symmetric keys
570
+ encrypted_keys = encrypted_package['k']
571
+
572
+ # 4. Identify this receiver's encrypted symmetric key
573
+ my_address = self.address
574
+ my_encrypted_key_hex = None
575
+ for ek in encrypted_keys:
576
+ if ek['a'] == my_address:
577
+ my_encrypted_key_hex = ek['k']
578
+ break
579
+
580
+ if my_encrypted_key_hex is None:
581
+ if debug:
582
+ self.P("No encrypted symmetric key for this receiver.", color='r')
583
+ return None
584
+
585
+ # Decode the encrypted symmetric key
586
+ my_encrypted_key = bytes.fromhex(my_encrypted_key_hex)
587
+
588
+ # The first 12 bytes are nonce_shared, rest is encrypted symmetric key
589
+ nonce_shared = my_encrypted_key[:12]
590
+ encrypted_symmetric_key = my_encrypted_key[12:]
591
+
592
+ # 5. Derive shared key using sender's public key
593
+ sender_pk = self._address_to_pk(sender_address)
594
+ shared_key = self.__derive_shared_key(sender_pk, info=info, debug=debug)
595
+
596
+ # 6. Decrypt the symmetric key
597
+ aesgcm_shared = AESGCM(shared_key)
598
+ symmetric_key = aesgcm_shared.decrypt(nonce_shared, encrypted_symmetric_key, None)
599
+
600
+ # 7. Decrypt the ciphertext using the symmetric key
601
+ aesgcm = AESGCM(symmetric_key)
602
+ plaintext = aesgcm.decrypt(nonce, ciphertext, None)
603
+
604
+ # 8. Decompress the plaintext if compressed_flag == 1
605
+ if compressed_flag == 1:
606
+ plaintext = zlib.decompress(plaintext)
607
+
608
+ return plaintext.decode()
609
+
610
+ except Exception as exc:
611
+ if debug:
612
+ self.P(f"Error decrypting multi scenario: {exc}", color='r')
613
+ return None
614
+
615
+ def decrypt(
616
+ self,
617
+ encrypted_data_b64: str,
618
+ sender_address: str,
619
+ info: str = BCct.DEFAULT_INFO,
620
+ debug: bool = False,
621
+ is_multi: bool = True
622
+ ):
623
+ """
624
+ Decrypts data encrypted for a single or multi receiver.
625
+
626
+ Parameters
627
+ ----------
628
+ encrypted_data_b64 : str
629
+ The base64 encoded encrypted data.
630
+
631
+ sender_address : str
632
+ The sender's address (public key address) used to derive the shared key.
633
+
634
+ info : str, optional
635
+ Additional info used in the HKDF for shared key derivation.
636
+
637
+ debug : bool, optional
638
+ If True, prints debug information.
639
+
640
+ is_multi : bool, optional
641
+ If True, decrypts as multi-recipient package.
642
+
643
+ Returns
644
+ -------
645
+ str or None
646
+ The decrypted plaintext as a string, or None if decryption fails.
647
+ """
648
+ result = None
649
+ if is_multi:
650
+ result = self.decrypt_for_multi(encrypted_data_b64, sender_address, info=info, debug=debug)
651
+ if result is None:
652
+ result = self._decrypt(encrypted_data_b64, sender_address, decompress=True, embed_compressed=True, info=info, debug=debug)
653
+ return result
654
+
655
+
656
+ ## end multi destination encryption
398
657
 
399
658
 
400
659
  ### ETH
@@ -3,7 +3,7 @@ from . import comms as COMMS
3
3
  from . import base as BASE_CT
4
4
  from . import payload as PAYLOAD_CT
5
5
  from .formatter import FORMATTER_DATA
6
- from .payload import STATUS_TYPE, PAYLOAD_DATA, COMMANDS, NOTIFICATION_CODES
6
+ from .payload import STATUS_TYPE, PAYLOAD_DATA, COMMANDS, NOTIFICATION_CODES, NET_CONFIG
7
7
  from .base import CONFIG_STREAM, BIZ_PLUGIN_DATA, PLUGIN_INFO, BLOCKCHAIN_CONFIG
8
8
  from . import heartbeat as HB
9
9
  from .environment import ENVIRONMENT
@@ -195,3 +195,9 @@ class PAYLOAD_DATA:
195
195
  ID_TAGS = 'ID_TAGS'
196
196
 
197
197
 
198
+ class NET_CONFIG:
199
+ STORE_COMMAND = "SET_CONFIG"
200
+ REQUEST_COMMAND = "GET_CONFIG"
201
+ NET_CONFIG_DATA = 'NET_CONFIG_DATA'
202
+ OPERATION = 'OP'
203
+ DESTINATION = 'DEST'
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "naeural_client"
7
- version = "2.3.5"
7
+ version = "2.4.0"
8
8
  authors = [
9
9
  { name="Andrei Ionut Damian", email="andrei.damian@me.com" },
10
10
  { name="Cristan Bleotiu", email="cristibleotiu@gmail.com" },
@@ -0,0 +1,52 @@
1
+ import json
2
+
3
+ from naeural_client import Logger, const
4
+ from naeural_client.bc import DefaultBlockEngine
5
+
6
+
7
+
8
+ if __name__ == '__main__' :
9
+ l = Logger("ENC", base_folder=".", app_folder="_local_cache")
10
+ eng1 = DefaultBlockEngine(
11
+ log=l, name="test1",
12
+ config={
13
+ "PEM_FILE" : "test1.pem",
14
+ "PASSWORD" : None,
15
+ "PEM_LOCATION" : "data"
16
+ }
17
+ )
18
+ eng2 = DefaultBlockEngine(
19
+ log=l, name="test2",
20
+ config={
21
+ "PEM_FILE" : "test2.pem",
22
+ "PASSWORD" : None,
23
+ "PEM_LOCATION" : "data"
24
+ }
25
+ )
26
+
27
+ data = {
28
+ "test1" : " ".join([f"data1-{x}" for x in range(1, 1000)]),
29
+ "test2" : [f"data2-{x}" for x in range(1, 1000)],
30
+ }
31
+
32
+ l.P("Non compressed test", color='g')
33
+ str_data = json.dumps(data)
34
+ l.P(f"Data size: {len(str_data)}")
35
+ encdata = eng1._encrypt(plaintext=str_data, receiver_address=eng2.address, compressed=False, embed_compressed=False)
36
+ l.P(f"Encrypted data (size: {len(encdata)})")
37
+ decdata = eng2._decrypt(encrypted_data_b64=encdata, sender_address=eng1.address, decompress=False, embed_compressed=False)
38
+ if decdata == str_data:
39
+ l.P("Decrypted data matches original data", color='g')
40
+ else:
41
+ l.P("Decrypted data does not match original data", color='r')
42
+
43
+ l.P("Compressed test", color='g')
44
+ str_data = json.dumps(data)
45
+ l.P(f"Data size: {len(str_data)}")
46
+ encdata = eng1.encrypt(plaintext=str_data, receiver_address=eng2.address)
47
+ l.P(f"Encrypted data (size: {len(encdata)})")
48
+ decdata = eng2.decrypt(encrypted_data_b64=encdata, sender_address=eng1.address)
49
+ if decdata == str_data:
50
+ l.P("Decrypted data matches original data", color='g')
51
+ else:
52
+ l.P("Decrypted data does not match original data", color='r')
@@ -0,0 +1,91 @@
1
+ import json
2
+
3
+ from naeural_client import Logger, const
4
+ from naeural_client.bc import DefaultBlockEngine
5
+
6
+
7
+
8
+ if __name__ == '__main__' :
9
+ l = Logger("ENC", base_folder=".", app_folder="_local_cache")
10
+ eng1 = DefaultBlockEngine(
11
+ log=l, name="test1",
12
+ config={
13
+ "PEM_FILE" : "test1.pem",
14
+ "PASSWORD" : None,
15
+ "PEM_LOCATION" : "data"
16
+ }
17
+ )
18
+
19
+ receivers = [
20
+ DefaultBlockEngine(
21
+ log=l, name=f"test{x}",
22
+ config={
23
+ "PEM_FILE" : f"test{x}.pem",
24
+ "PASSWORD" : None,
25
+ "PEM_LOCATION" : "data"
26
+ }
27
+ ) for x in range(2, 7)
28
+ ]
29
+
30
+
31
+ bandit = DefaultBlockEngine( # bandit
32
+ log=l, name="bandit",
33
+ config={
34
+ "PEM_FILE" : "bandit.pem",
35
+ "PASSWORD" : None,
36
+ "PEM_LOCATION" : "data"
37
+ }
38
+ )
39
+
40
+ data = {
41
+ "test1" : " ".join([f"data1-{x}" for x in range(1, 1000)]),
42
+ "test2" : [f"data2-{x}" for x in range(1, 1000)],
43
+ }
44
+
45
+ str_data = json.dumps(data)
46
+ l.P("Data size: {}".format(len(str_data)), color='b')
47
+ enc_data1s = eng1.encrypt(
48
+ plaintext=str_data,
49
+ receiver_address=receivers[0].address, debug=True
50
+ )
51
+ enc_data1m = eng1.encrypt_for_multi(
52
+ plaintext=str_data,
53
+ receiver_addresses=[x.address for x in receivers]
54
+ )
55
+ l.P("Encrypted data size: {}".format(len(enc_data1m)), color='b')
56
+ receivers.append(bandit) # bandit inserts itself into the list of receivers
57
+ single = receivers[0]
58
+ bandit = receivers[-1]
59
+
60
+ decdata = single.decrypt(
61
+ encrypted_data_b64=enc_data1s,
62
+ sender_address=eng1.address,
63
+ debug=False,
64
+ )
65
+ if decdata == str_data:
66
+ l.P(f"Data (single) successfully decrypted by {single.name}", color='g')
67
+ else:
68
+ l.P(f"Data (single) decryption failed by {single.name}", color='r')
69
+
70
+ decdata = bandit.decrypt(
71
+ encrypted_data_b64=enc_data1s,
72
+ sender_address=eng1.address,
73
+ debug=False,
74
+ )
75
+ if decdata == str_data:
76
+ l.P(f"Data (single) successfully decrypted by {bandit.name}", color='g')
77
+ else:
78
+ l.P(f"Data (single) decryption failed by {bandit.name}", color='r')
79
+
80
+
81
+ for receiver in receivers:
82
+ decdata = receiver.decrypt(
83
+ encrypted_data_b64=enc_data1m,
84
+ sender_address=eng1.address,
85
+ debug=False,
86
+ )
87
+ if decdata == str_data:
88
+ l.P("Data (multi) successfully decrypted by {}".format(receiver.name), color='g')
89
+ else:
90
+ l.P("Data (multi) decryption failed by {}".format(receiver.name), color='r')
91
+
@@ -1,74 +0,0 @@
1
- import json
2
-
3
- from naeural_client import Logger, const
4
- from naeural_client.bc import DefaultBlockEngine
5
-
6
-
7
-
8
- if __name__ == '__main__' :
9
- l = Logger("ENC", base_folder=".", app_folder="_local_cache")
10
- eng1 = DefaultBlockEngine(
11
- log=l, name="test1",
12
- config={
13
- "PEM_FILE" : "test1.pem",
14
- "PASSWORD" : None,
15
- "PEM_LOCATION" : "data"
16
- }
17
- )
18
- eng2 = DefaultBlockEngine(
19
- log=l, name="test2",
20
- config={
21
- "PEM_FILE" : "test2.pem",
22
- "PASSWORD" : None,
23
- "PEM_LOCATION" : "data"
24
- }
25
- )
26
-
27
- data = {
28
- "test": "data1 data2 data3 data4 data5 data6 data7 data8 data9 data10",
29
- "test2": "data21 data22 data23 data24 data25 data26 data27 data28 data29 data210",
30
- "test3": "data31 data32 data33 data34 data35 data36 data37 data38 data39 data310",
31
- "test4" : {
32
- "test5": "data5 data6 data7 data8 data9 data10 data11 data12 data13 data14",
33
- "test6": "data6 data7 data8 data9 data10 data11 data12 data13 data14 data15",
34
- "test7": [
35
- "data7",
36
- {
37
- "test9": "data91 data92 data93 data94 data95 data96 data97 data98 data99 data910",
38
- "test10": "data10 data11 data12 data13 data14 data15 data16 data17 data18 data19 data110",
39
- }
40
- ]
41
- }
42
- }
43
-
44
- l.P("Non compressed test", color='g')
45
- str_data = json.dumps(data)
46
- l.P(f"Data size: {len(str_data)}")
47
- encdata = eng1.encrypt(plaintext=str_data, receiver_address=eng2.address, compressed=False, embed_compressed=False)
48
- l.P(f"Encrypted data (size: {len(encdata)}): {encdata}")
49
- decdata = eng2.decrypt(encrypted_data_b64=encdata, sender_address=eng1.address, decompress=False, embed_compressed=False)
50
- l.P(f"Decrypted data:\n {json.dumps(json.loads(decdata), indent=2)}")
51
-
52
- l.P("Compressed test", color='g')
53
- str_data = json.dumps(data)
54
- l.P(f"Data size: {len(str_data)}")
55
- encdata = eng1.encrypt(plaintext=str_data, receiver_address=eng2.address, compressed=True, embed_compressed=False)
56
- l.P(f"Encrypted data (size: {len(encdata)}): {encdata}")
57
- decdata = eng2.decrypt(encrypted_data_b64=encdata, sender_address=eng1.address, decompress=True, embed_compressed=False)
58
- l.P(f"Decrypted data:\n {json.dumps(json.loads(decdata), indent=2)}")
59
-
60
- l.P("Compressed test with embed", color='g')
61
- str_data = json.dumps(data)
62
- l.P(f"Data size: {len(str_data)}")
63
- encdata = eng1.encrypt(plaintext=str_data, receiver_address=eng2.address, compressed=True, embed_compressed=True)
64
- l.P(f"Encrypted data (size: {len(encdata)}): {encdata}")
65
- decdata = eng2.decrypt(encrypted_data_b64=encdata, sender_address=eng1.address, embed_compressed=True) # decompress does not matter
66
- l.P(f"Decrypted data:\n {json.dumps(json.loads(decdata), indent=2)}")
67
-
68
- l.P("Default test", color='g')
69
- str_data = json.dumps(data)
70
- l.P(f"Data size: {len(str_data)}")
71
- encdata = eng1.encrypt(plaintext=str_data, receiver_address=eng2.address)
72
- l.P(f"Encrypted data (size: {len(encdata)}): {encdata}")
73
- decdata = eng2.decrypt(encrypted_data_b64=encdata, sender_address=eng1.address)
74
- l.P(f"Decrypted data:\n {json.dumps(json.loads(decdata), indent=2)}")
File without changes
File without changes
File without changes