@ethernity-cloud/sdk-js 1.6.2 → 1.7.0

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 (51) hide show
  1. package/README.md +41 -3
  2. package/cas/config.js +59 -1
  3. package/info.js +14 -5
  4. package/init.js +20 -4
  5. package/nodenithy/build/securelock/Dockerfile.tmpl +34 -32
  6. package/nodenithy/build/securelock/scripts/binary-fs-build.sh +7 -6
  7. package/nodenithy/build.mjs +80 -68
  8. package/nodenithy/run/docker-compose-final.yml.tmpl +36 -31
  9. package/nodenithy/run/docker-compose.yml.tmpl +34 -45
  10. package/nodenithy/run/image_registry.js +17 -4
  11. package/nodenithy/run.js +42 -28
  12. package/package.json +5 -3
  13. package/publish.js +4 -2
  14. package/pynithy/build/securelock/Dockerfile.base.tpl +13 -0
  15. package/pynithy/build/securelock/Dockerfile.tpl +131 -0
  16. package/pynithy/build/securelock/scripts/binary-fs-build.sh +25 -34
  17. package/pynithy/build/securelock/scripts/pyfreeze.sh +32 -0
  18. package/pynithy/build/securelock/src/{pox.abi → abi/etnyImplementationV2.abi} +1489 -1489
  19. package/pynithy/build/securelock/src/abi/image_registry.abi +1 -0
  20. package/pynithy/build/securelock/src/ecld_state.py +906 -0
  21. package/pynithy/build/securelock/src/esr.abi +1 -0
  22. package/pynithy/build/securelock/src/esr_local.py +267 -0
  23. package/pynithy/build/securelock/src/esr_wallet.py +150 -0
  24. package/pynithy/build/securelock/src/etny_crypto.py +208 -167
  25. package/pynithy/build/securelock/src/etny_exec.py +385 -79
  26. package/pynithy/build/securelock/src/etny_exec_flask.py +535 -0
  27. package/pynithy/build/securelock/src/etny_exec_serv.py +353 -0
  28. package/pynithy/build/securelock/src/etny_session_exec.py +245 -0
  29. package/pynithy/build/securelock/src/get_sgx_report.so +0 -0
  30. package/pynithy/build/securelock/src/image_registry.abi +1 -1
  31. package/pynithy/build/securelock/src/key_generation.py +17 -17
  32. package/pynithy/build/securelock/src/local_api.py +189 -0
  33. package/pynithy/build/securelock/src/models.py +200 -176
  34. package/pynithy/build/securelock/src/securelock.py.tmpl +1037 -731
  35. package/pynithy/build/securelock/src/swift_stream_service.py +206 -186
  36. package/pynithy/build.mjs +139 -89
  37. package/pynithy/run/docker-compose-final.yml.tmpl +58 -51
  38. package/pynithy/run/docker-compose.yml.tmpl +62 -48
  39. package/pynithy/run/etny-securelock-test.yaml.tpl +4 -1
  40. package/pynithy/run/image_registry.js +17 -4
  41. package/pynithy/run.js +44 -28
  42. package/pynithy/src/serverless/Dockerfile.serverless +8 -0
  43. package/pynithy/src/serverless/requirements.txt +6 -0
  44. package/run.js +69 -28
  45. package/nodenithy/build/las/Dockerfile +0 -5
  46. package/pynithy/build/docker-compose.yml +0 -70
  47. package/pynithy/build/las/Dockerfile +0 -11
  48. package/pynithy/build/las/src/etny_entrypoint.sh +0 -6
  49. package/pynithy/build/las/src/las_entrypoint.sh +0 -26
  50. package/pynithy/build/scripts/binary-fs-build.sh +0 -28
  51. package/pynithy/build/securelock/Dockerfile.tmpl +0 -95
@@ -1,167 +1,208 @@
1
- from __future__ import annotations
2
-
3
- import base64
4
- import binascii
5
- import codecs
6
- import hashlib
7
- import json
8
- import secrets
9
- from pyasn1.codec.der import decoder
10
- from Crypto.Cipher import AES
11
- from tinyec import registry
12
- from tinyec import ec
13
- from Crypto.PublicKey import ECC
14
- from nacl.public import Box, PrivateKey, PublicKey
15
- from base64 import a85encode
16
-
17
-
18
- class etny_crypto:
19
- curve = registry.get_curve('secp384r1')
20
-
21
- @staticmethod
22
- def compress_point(point):
23
- return hex(point.x) + hex(point.y % 2)[2:]
24
-
25
- @staticmethod
26
- def ecc_point_to_256_bit_key(point):
27
- value = str(point.x) + str(point.y)
28
- sha = hashlib.sha256(value.encode())
29
- return sha.digest()
30
-
31
- @staticmethod
32
- def encrypt_aes_gcm(msg, secret_key):
33
- aes_cipher = AES.new(secret_key, AES.MODE_GCM)
34
- cipher_text, auth_tag = aes_cipher.encrypt_and_digest(msg)
35
- return (cipher_text, aes_cipher.nonce, auth_tag)
36
-
37
- @staticmethod
38
- def encrypt_ecc(msg, public_key):
39
- cipher_text_private_key = secrets.randbelow(etny_crypto.curve.field.n)
40
- shared_ecc_key = cipher_text_private_key * public_key
41
- secret_key = etny_crypto.ecc_point_to_256_bit_key(shared_ecc_key)
42
- ciphertext, nonce, auth_tag = etny_crypto.encrypt_aes_gcm(msg, secret_key)
43
- cipher_text_public_key = cipher_text_private_key * etny_crypto.curve.g
44
- return (ciphertext, nonce, auth_tag, cipher_text_public_key)
45
-
46
- @staticmethod
47
- def decrypt_ase_gcm(ciphertext, nonce, auth_tag, secret_key):
48
- aes_cipher = AES.new(secret_key, AES.MODE_GCM, nonce)
49
- plaintext = aes_cipher.decrypt_and_verify(ciphertext, auth_tag)
50
- return plaintext
51
-
52
- @staticmethod
53
- def decrypt_ecc(encrypted_msg, priv_key):
54
- (ciphertext, nonce, authTag, ciphertextPubKey) = encrypted_msg
55
- shared_ecc_key = priv_key * ciphertextPubKey
56
- secret_key = etny_crypto.ecc_point_to_256_bit_key(shared_ecc_key)
57
- plaintext = etny_crypto.decrypt_ase_gcm(ciphertext, nonce, authTag, secret_key)
58
- return plaintext
59
-
60
- @staticmethod
61
- def ecc_read_key(public_key_file):
62
- with open(public_key_file) as r:
63
- key = ECC.import_key(r.read())
64
- return key
65
-
66
- @staticmethod
67
- def encrypt(public_key_file, message):
68
- with open(public_key_file) as f:
69
- ecc_public_cert = ECC.import_key(f.read())
70
- pub_key_ecc_point = ec.Point(etny_crypto.curve, ecc_public_cert.pointQ.x.__int__(),
71
- ecc_public_cert.pointQ.y.__int__())
72
- encrypted_msg = etny_crypto.encrypt_ecc(message, pub_key_ecc_point)
73
- return encrypted_msg
74
-
75
- @staticmethod
76
- def encrypt_with_pub_key(pub_key_content, message):
77
- ecc_public_cert = ECC.import_key(pub_key_content)
78
- pub_key_ecc_point = ec.Point(etny_crypto.curve, ecc_public_cert.pointQ.x.__int__(),
79
- ecc_public_cert.pointQ.y.__int__())
80
- encrypted_msg = etny_crypto.encrypt_ecc(message, pub_key_ecc_point)
81
- return encrypted_msg
82
-
83
- @staticmethod
84
- def clean_private_key(private_key_data):
85
- private_key_data = private_key_data.replace(b"-----BEGIN PRIVATE KEY-----", b"")
86
- private_key_data = private_key_data.replace(b"-----END PRIVATE KEY-----", b"")
87
- private_key_data = codecs.decode(private_key_data, 'base64')
88
- return private_key_data
89
-
90
- @staticmethod
91
- def decrypt(private_key_file, encrypted_msg):
92
- # Reading and calculating Private Key from PEM
93
- with open(private_key_file) as f:
94
- private_key_data = str.encode(f.read())
95
-
96
- private_key_data = etny_crypto.clean_private_key(private_key_data)
97
- # decode der with asn1 library
98
- # - get the octet string (field-2) containing the raw key
99
- asn1_object, _ = decoder.decode(private_key_data)
100
- raw_keys = asn1_object.getComponentByName('field-2').asOctets()
101
- # - get the octet string (field-1) containing the raw private key
102
- # and the bit string (field-2) containing the uncompressed public key
103
- asn1_object, _ = decoder.decode(raw_keys)
104
- private_key = asn1_object.getComponentByName('field-1').asOctets()
105
-
106
- # Generating keypair for tinyEC
107
- priv_key_tec = int.from_bytes(private_key, byteorder="big")
108
- decrypted_msg = etny_crypto.decrypt_ecc(encrypted_msg, priv_key_tec)
109
- #print("\ndecrypted msg:", decrypted_msg)
110
- return decrypted_msg
111
-
112
- @staticmethod
113
- def encrypted_data_to_base64_json(encrypted_msg):
114
- json_obj = {
115
- 'ciphertext': binascii.hexlify(encrypted_msg[0]).decode(),
116
- 'nonce': binascii.hexlify(encrypted_msg[1]).decode(),
117
- 'authTag': binascii.hexlify(encrypted_msg[2]).decode(),
118
- 'x': hex(encrypted_msg[3].x),
119
- 'y': hex(encrypted_msg[3].y)
120
- }
121
-
122
- json_string = json.dumps(json_obj)
123
- binary_data = json_string.encode('utf-8')
124
- base64_data = base64.b64encode(binary_data)
125
-
126
- return base64_data
127
-
128
- @staticmethod
129
- def encrypted_data_from_base64_json(base64_data):
130
- # decode the base64-encoded string back to a JSON string
131
- decoded_json_data = base64.b64decode(base64_data).decode('utf-8')
132
-
133
- json_load = json.loads(decoded_json_data)
134
- return (binascii.unhexlify(json_load['ciphertext'].encode()),
135
- binascii.unhexlify(json_load['nonce'].encode()),
136
- binascii.unhexlify(json_load['authTag'].encode()),
137
- ec.Point(etny_crypto.curve, int(json_load['x'], 16),
138
- int(json_load['y'], 16)))
139
-
140
- @staticmethod
141
- def hex_to_bytes(hex_str: str) -> bytes:
142
- return bytes.fromhex(hex_str[2:] if hex_str[:2] == "0x" else hex_str)
143
-
144
- @staticmethod
145
- def encrypt_nacl(public_key: str, data: bytes) -> str:
146
- """Encryption function using NaCl box compatible with MetaMask
147
- For implementation used in MetaMask look into: https://github.com/MetaMask/eth-sig-util
148
- Args:
149
- public_key: public key of recipient (32 bytes)
150
- data: message data
151
- Returns:
152
- encrypted data
153
- """
154
- emph_key = PrivateKey.generate()
155
- enc_box = Box(emph_key, PublicKey(etny_crypto.hex_to_bytes(public_key)))
156
- # Encryption must work with MetaMask decryption (requires valid utf-8)
157
- data = a85encode(data)
158
- ciphertext = enc_box.encrypt(data)
159
- result = bytes(emph_key.public_key) + ciphertext
160
- return result.hex()
161
-
162
-
163
- if __name__ == '__main__':
164
- encrypted_msg_ = etny_crypto.encrypt('./app/cert1-ca1-clean.crt', b'test')
165
- #print(encrypted_msg_)
166
- # etny_crypto.decrypt('./certs/cert1-ca1-clean.key', encrypted_msg_)
167
- #print(etny_crypto.encrypted_data_to_base64_json(encrypted_msg_))
1
+ from __future__ import annotations
2
+
3
+ import base64
4
+ import binascii
5
+ import codecs
6
+ import hashlib
7
+ import json
8
+ import secrets
9
+ from pyasn1.codec.der import decoder
10
+ from Crypto.Cipher import AES
11
+ from tinyec import registry
12
+ from tinyec import ec
13
+ from Crypto.PublicKey import ECC
14
+ from nacl.public import Box, PrivateKey, PublicKey
15
+ from base64 import a85encode
16
+ from eth_account import Account
17
+ import ecdsa
18
+ from ecdsa.util import sigencode_der, sigdecode_der
19
+
20
+
21
+ class etny_crypto:
22
+ curve = registry.get_curve('secp384r1')
23
+
24
+ @staticmethod
25
+ def compress_point(point):
26
+ return hex(point.x) + hex(point.y % 2)[2:]
27
+
28
+ @staticmethod
29
+ def ecc_point_to_256_bit_key(point):
30
+ value = str(point.x) + str(point.y)
31
+ sha = hashlib.sha256(value.encode())
32
+ return sha.digest()
33
+
34
+ @staticmethod
35
+ def encrypt_aes_gcm(msg, secret_key):
36
+ aes_cipher = AES.new(secret_key, AES.MODE_GCM)
37
+ cipher_text, auth_tag = aes_cipher.encrypt_and_digest(msg)
38
+ return (cipher_text, aes_cipher.nonce, auth_tag)
39
+
40
+ @staticmethod
41
+ def encrypt_ecc(msg, public_key):
42
+ cipher_text_private_key = secrets.randbelow(etny_crypto.curve.field.n)
43
+ shared_ecc_key = cipher_text_private_key * public_key
44
+ secret_key = etny_crypto.ecc_point_to_256_bit_key(shared_ecc_key)
45
+ ciphertext, nonce, auth_tag = etny_crypto.encrypt_aes_gcm(msg, secret_key)
46
+ cipher_text_public_key = cipher_text_private_key * etny_crypto.curve.g
47
+ return (ciphertext, nonce, auth_tag, cipher_text_public_key)
48
+
49
+ @staticmethod
50
+ def decrypt_aes_gcm(ciphertext, nonce, auth_tag, secret_key):
51
+ aes_cipher = AES.new(secret_key, AES.MODE_GCM, nonce)
52
+ plaintext = aes_cipher.decrypt_and_verify(ciphertext, auth_tag)
53
+ return plaintext
54
+
55
+ @staticmethod
56
+ def decrypt_ecc(encrypted_msg, priv_key):
57
+ (ciphertext, nonce, authTag, ciphertextPubKey) = encrypted_msg
58
+ shared_ecc_key = priv_key * ciphertextPubKey
59
+ secret_key = etny_crypto.ecc_point_to_256_bit_key(shared_ecc_key)
60
+ plaintext = etny_crypto.decrypt_aes_gcm(ciphertext, nonce, authTag, secret_key)
61
+ return plaintext
62
+
63
+ @staticmethod
64
+ def ecc_read_key(public_key_file):
65
+ with open(public_key_file) as r:
66
+ key = ECC.import_key(r.read())
67
+ return key
68
+
69
+ @staticmethod
70
+ def encrypt(public_key_file, message):
71
+ with open(public_key_file) as f:
72
+ ecc_public_cert = ECC.import_key(f.read())
73
+ pub_key_ecc_point = ec.Point(etny_crypto.curve, ecc_public_cert.pointQ.x.__int__(),
74
+ ecc_public_cert.pointQ.y.__int__())
75
+ encrypted_msg = etny_crypto.encrypt_ecc(message, pub_key_ecc_point)
76
+ return encrypted_msg
77
+
78
+ @staticmethod
79
+ def encrypt_with_pub_key(pub_key_content, message):
80
+ ecc_public_cert = ECC.import_key(pub_key_content)
81
+ pub_key_ecc_point = ec.Point(etny_crypto.curve, ecc_public_cert.pointQ.x.__int__(),
82
+ ecc_public_cert.pointQ.y.__int__())
83
+ encrypted_msg = etny_crypto.encrypt_ecc(message, pub_key_ecc_point)
84
+ return encrypted_msg
85
+
86
+ @staticmethod
87
+ def clean_private_key(private_key_data):
88
+ private_key_data = private_key_data.replace(b"-----BEGIN PRIVATE KEY-----", b"")
89
+ private_key_data = private_key_data.replace(b"-----END PRIVATE KEY-----", b"")
90
+ private_key_data = codecs.decode(private_key_data, 'base64')
91
+ return private_key_data
92
+
93
+ @staticmethod
94
+ def decrypt(private_key_pem, encrypted_msg):
95
+ private_key_data = etny_crypto.clean_private_key(private_key_pem)
96
+ # decode der with asn1 library
97
+ # - get the octet string (field-2) containing the raw key
98
+ asn1_object, _ = decoder.decode(private_key_data)
99
+ raw_keys = asn1_object.getComponentByName('field-2').asOctets()
100
+ # - get the octet string (field-1) containing the raw private key
101
+ # and the bit string (field-2) containing the uncompressed public key
102
+ asn1_object, _ = decoder.decode(raw_keys)
103
+ private_key = asn1_object.getComponentByName('field-1').asOctets()
104
+
105
+ # Generating keypair for tinyEC
106
+ priv_key_tec = int.from_bytes(private_key, byteorder="big")
107
+ decrypted_msg = etny_crypto.decrypt_ecc(encrypted_msg, priv_key_tec)
108
+ #print("\ndecrypted msg:", decrypted_msg)
109
+ return decrypted_msg
110
+
111
+ @staticmethod
112
+ def encrypted_data_to_base64_json(encrypted_msg):
113
+ json_obj = {
114
+ 'ciphertext': binascii.hexlify(encrypted_msg[0]).decode(),
115
+ 'nonce': binascii.hexlify(encrypted_msg[1]).decode(),
116
+ 'authTag': binascii.hexlify(encrypted_msg[2]).decode(),
117
+ 'x': hex(encrypted_msg[3].x),
118
+ 'y': hex(encrypted_msg[3].y)
119
+ }
120
+
121
+ json_string = json.dumps(json_obj)
122
+ binary_data = json_string.encode('utf-8')
123
+ base64_data = base64.b64encode(binary_data)
124
+
125
+ return base64_data
126
+
127
+ @staticmethod
128
+ def encrypted_data_from_base64_json(base64_data):
129
+ # decode the base64-encoded string back to a JSON string
130
+ decoded_json_data = base64.b64decode(base64_data).decode('utf-8')
131
+
132
+ json_load = json.loads(decoded_json_data)
133
+ return (binascii.unhexlify(json_load['ciphertext'].encode()),
134
+ binascii.unhexlify(json_load['nonce'].encode()),
135
+ binascii.unhexlify(json_load['authTag'].encode()),
136
+ ec.Point(etny_crypto.curve, int(json_load['x'], 16),
137
+ int(json_load['y'], 16)))
138
+
139
+ @staticmethod
140
+ def hex_to_bytes(hex_str: str) -> bytes:
141
+ return bytes.fromhex(hex_str[2:] if hex_str[:2] == "0x" else hex_str)
142
+
143
+ @staticmethod
144
+ def encrypt_nacl(public_key: str, data: bytes) -> str:
145
+ """Encryption function using NaCl box compatible with MetaMask
146
+ For implementation used in MetaMask look into: https://github.com/MetaMask/eth-sig-util
147
+ Args:
148
+ public_key: public key of recipient (32 bytes)
149
+ data: message data
150
+ Returns:
151
+ encrypted data
152
+ """
153
+ emph_key = PrivateKey.generate()
154
+ enc_box = Box(emph_key, PublicKey(etny_crypto.hex_to_bytes(public_key)))
155
+ # Encryption must work with MetaMask decryption (requires valid utf-8)
156
+ data = a85encode(data)
157
+ ciphertext = enc_box.encrypt(data)
158
+ result = bytes(emph_key.public_key) + ciphertext
159
+ return result.hex()
160
+
161
+ @staticmethod
162
+ def get_private_key_int(private_key_pem: bytes) -> int:
163
+ """
164
+ Extracts the raw private key integer from a PEM-encoded private key via ASN.1 decoding.
165
+ Args:
166
+ private_key_pem (bytes): PEM-encoded private key.
167
+ Returns:
168
+ int: The private key scalar.
169
+ """
170
+ private_key = etny_crypto.clean_private_key(private_key_pem)
171
+ asn1_object, _ = decoder.decode(private_key)
172
+ raw_keys = asn1_object.getComponentByName('field-2').asOctets()
173
+ asn1_object, _ = decoder.decode(raw_keys)
174
+ private_key_bytes = asn1_object.getComponentByName('field-1').asOctets()
175
+ return int.from_bytes(private_key_bytes, byteorder="big")
176
+
177
+ @staticmethod
178
+ def sign_data(private_key_pem: bytes, data: bytes) -> bytes:
179
+ """
180
+ Signs data using the private key with ECDSA (secp384r1, SHA-256) and returns DER-encoded signature.
181
+ Args:
182
+ private_key_pem (bytes): PEM-encoded private key.
183
+ data (bytes): Data to sign.
184
+ Returns:
185
+ bytes: DER-encoded signature.
186
+ """
187
+ priv_int = etny_crypto.get_private_key_int(private_key_pem)
188
+ sk = ecdsa.SigningKey.from_secret_exponent(priv_int, curve=ecdsa.curves.NIST384p, hashfunc=hashlib.sha256)
189
+ sig_der = sk.sign_deterministic(data, hashfunc=hashlib.sha256, sigencode=sigencode_der)
190
+ return sig_der
191
+
192
+ @staticmethod
193
+ def verify_signature(public_key_hex: str, data: bytes, sig_der: bytes) -> bool:
194
+ if public_key_hex.startswith('0x'):
195
+ public_key_hex = public_key_hex[2:]
196
+ pub_bytes = bytes.fromhex(public_key_hex)
197
+ curve = ecdsa.curves.NIST384p
198
+ try:
199
+ vk = ecdsa.VerifyingKey.from_string(
200
+ pub_bytes,
201
+ curve=curve,
202
+ hashfunc=hashlib.sha256,
203
+ valid_encodings={"raw", "compressed", "uncompressed", "hybrid"} # Add 'raw' here
204
+ )
205
+ assert vk.verify(sig_der, data, hashfunc=hashlib.sha256, sigdecode=sigdecode_der)
206
+ return True
207
+ except:
208
+ return False