huaweicloud-encryption-sdk-python 1.2.1__py3-none-any.whl
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.
- examples/file_encryption_example.py +57 -0
- examples/key_capsule_encryption_example.py +240 -0
- examples/kms_discovery_encryption_example.py +56 -0
- examples/local_aes_encryption_example.py +59 -0
- examples/test_rsa.py +42 -0
- examples/test_sm2.py +38 -0
- examples/test_sm4_cbc.py +37 -0
- examples/test_sm4_gcm.py +37 -0
- huaweicloud_encryption_sdk_python-1.2.1.dist-info/METADATA +18 -0
- huaweicloud_encryption_sdk_python-1.2.1.dist-info/RECORD +174 -0
- huaweicloud_encryption_sdk_python-1.2.1.dist-info/WHEEL +5 -0
- huaweicloud_encryption_sdk_python-1.2.1.dist-info/top_level.txt +3 -0
- huaweicloud_encryptionsdk/__init__.py +5 -0
- huaweicloud_encryptionsdk/_apig_sdk/__init__.py +1 -0
- huaweicloud_encryptionsdk/_apig_sdk/signer.py +278 -0
- huaweicloud_encryptionsdk/_apig_sdk/signer_v11.py +70 -0
- huaweicloud_encryptionsdk/_apig_sdk/sm3_hash.py +141 -0
- huaweicloud_encryptionsdk/_lts_sdk/auth/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/auth/signer.py +174 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/client/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/client/consumer_client_adapter.py +59 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/client/http_client.py +211 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/core/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/core/client_consumer_worker.py +106 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/core/consumer_heartbeat.py +73 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/core/log_shard_consumer.py +179 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/interface/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/interface/consumer_check_point_tracker.py +120 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/interface/consumer_processor.py +18 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/interface/consumer_processor_factory.py +3 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/model/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/model/check_point.py +20 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/model/consumer_config.py +27 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/model/log_data.py +18 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/model/task_result.py +40 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/task/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/task/consumer_fetch_task.py +53 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/task/initial_task.py +55 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/task/process_task.py +25 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/task/shutdown_task.py +24 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer_main.py +88 -0
- huaweicloud_encryptionsdk/_lts_sdk/parallel_main.py +64 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/callback/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/callback/call_back.py +7 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/core/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/core/accumulator.py +135 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/core/io_thread_pool.py +107 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/core/io_worker.py +124 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/core/mover.py +69 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/core/producer.py +98 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/lts_http/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/lts_http/http_client.py +63 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/lts_http/simple_request.py +14 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/model/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/model/config.py +50 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/model/error.py +18 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/model/log.py +87 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/model/log_batch.py +154 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/model/lts_store.py +21 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/model/result.py +17 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/model/retry_queue.py +39 -0
- huaweicloud_encryptionsdk/_lts_sdk/serial_main.py +77 -0
- huaweicloud_encryptionsdk/_lts_sdk/utils/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/utils/common.py +57 -0
- huaweicloud_encryptionsdk/_lts_sdk/utils/lts_threading.py +32 -0
- huaweicloud_encryptionsdk/cache/__init__.py +0 -0
- huaweicloud_encryptionsdk/cache/data_key_cache.py +79 -0
- huaweicloud_encryptionsdk/cache/local_data_key_cache.py +161 -0
- huaweicloud_encryptionsdk/common/__init__.py +0 -0
- huaweicloud_encryptionsdk/common/constants.py +15 -0
- huaweicloud_encryptionsdk/common/counting_output_stream.py +18 -0
- huaweicloud_encryptionsdk/common/crypto_factory.py +48 -0
- huaweicloud_encryptionsdk/common/ec_private_key_loader.py +43 -0
- huaweicloud_encryptionsdk/common/ecs_metadata_service.py +42 -0
- huaweicloud_encryptionsdk/common/file_path_for_example_constants.py +4 -0
- huaweicloud_encryptionsdk/common/utils.py +162 -0
- huaweicloud_encryptionsdk/exception/__init__.py +0 -0
- huaweicloud_encryptionsdk/exception/errors.py +109 -0
- huaweicloud_encryptionsdk/handler/__init__.py +0 -0
- huaweicloud_encryptionsdk/handler/cipher_handler.py +294 -0
- huaweicloud_encryptionsdk/handler/crypto_handler.py +24 -0
- huaweicloud_encryptionsdk/handler/default_crypto_handler.py +148 -0
- huaweicloud_encryptionsdk/handler/default_serialize_handler.py +45 -0
- huaweicloud_encryptionsdk/handler/file_decrypt_handler.py +101 -0
- huaweicloud_encryptionsdk/handler/file_encrypt_handler.py +30 -0
- huaweicloud_encryptionsdk/handler/serialize_handler.py +14 -0
- huaweicloud_encryptionsdk/huawei_config.py +49 -0
- huaweicloud_encryptionsdk/huawei_crypto.py +311 -0
- huaweicloud_encryptionsdk/keyrings/__init__.py +0 -0
- huaweicloud_encryptionsdk/keyrings/keyring.py +14 -0
- huaweicloud_encryptionsdk/keyrings/keyring_factory.py +10 -0
- huaweicloud_encryptionsdk/keyrings/kms_keyring_factory.py +21 -0
- huaweicloud_encryptionsdk/keyrings/kmskeyring/__init__.py +0 -0
- huaweicloud_encryptionsdk/keyrings/kmskeyring/kms_discovery_keyring.py +51 -0
- huaweicloud_encryptionsdk/keyrings/kmskeyring/kms_key_capsule_keyring.py +100 -0
- huaweicloud_encryptionsdk/keyrings/kmskeyring/kms_keyring.py +155 -0
- huaweicloud_encryptionsdk/keyrings/kmskeyring/kms_multi_region_keyring.py +8 -0
- huaweicloud_encryptionsdk/keyrings/raw_keyring_factory.py +27 -0
- huaweicloud_encryptionsdk/keyrings/rawkeyring/__init__.py +0 -0
- huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_aes_keyring.py +63 -0
- huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_keyring.py +112 -0
- huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_rsa_keyring.py +55 -0
- huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_sm2_keyring.py +75 -0
- huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_sm4_cbc_keyring.py +66 -0
- huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_sm4_keyring.py +70 -0
- huaweicloud_encryptionsdk/kms/__init__.py +0 -0
- huaweicloud_encryptionsdk/kms/create_key_capsule_request.py +35 -0
- huaweicloud_encryptionsdk/kms/create_key_capsule_response.py +19 -0
- huaweicloud_encryptionsdk/kms/decrypt_key_capsule_request.py +32 -0
- huaweicloud_encryptionsdk/kms/decrypt_key_capsule_response.py +19 -0
- huaweicloud_encryptionsdk/kms/kms_http_client.py +116 -0
- huaweicloud_encryptionsdk/log/__init__.py +0 -0
- huaweicloud_encryptionsdk/log/log_config.py +30 -0
- huaweicloud_encryptionsdk/log/log_file_backup.py +144 -0
- huaweicloud_encryptionsdk/log/log_metrics.py +132 -0
- huaweicloud_encryptionsdk/log/log_reporter_manager.py +163 -0
- huaweicloud_encryptionsdk/log/lts_sdk_producer.py +386 -0
- huaweicloud_encryptionsdk/log/lts_struct_log_builder.py +106 -0
- huaweicloud_encryptionsdk/meterialmanager/__init__.py +0 -0
- huaweicloud_encryptionsdk/meterialmanager/cache_crypto_meterial_manager.py +221 -0
- huaweicloud_encryptionsdk/meterialmanager/crypto_meterial_manager.py +19 -0
- huaweicloud_encryptionsdk/meterialmanager/data_key_generate.py +10 -0
- huaweicloud_encryptionsdk/meterialmanager/data_key_generate_factory.py +20 -0
- huaweicloud_encryptionsdk/meterialmanager/default_crypto_meterials_manager.py +71 -0
- huaweicloud_encryptionsdk/meterialmanager/key_capsule_data_key_generate.py +63 -0
- huaweicloud_encryptionsdk/meterialmanager/kms_data_key_generate.py +65 -0
- huaweicloud_encryptionsdk/meterialmanager/local_data_key_generate.py +13 -0
- huaweicloud_encryptionsdk/model/__init__.py +0 -0
- huaweicloud_encryptionsdk/model/access_point_config.py +9 -0
- huaweicloud_encryptionsdk/model/cipher_body.py +81 -0
- huaweicloud_encryptionsdk/model/cipher_header.py +405 -0
- huaweicloud_encryptionsdk/model/ciphertext_data_key.py +166 -0
- huaweicloud_encryptionsdk/model/crypto_result.py +11 -0
- huaweicloud_encryptionsdk/model/data_key_materials.py +17 -0
- huaweicloud_encryptionsdk/model/data_materials.py +11 -0
- huaweicloud_encryptionsdk/model/enums/__init__.py +0 -0
- huaweicloud_encryptionsdk/model/enums/access_point_type.py +28 -0
- huaweicloud_encryptionsdk/model/enums/crypto_algorithm.py +75 -0
- huaweicloud_encryptionsdk/model/enums/data_key_generate_type.py +20 -0
- huaweicloud_encryptionsdk/model/enums/key_provider_enum.py +19 -0
- huaweicloud_encryptionsdk/model/enums/keyring_type_enum.py +27 -0
- huaweicloud_encryptionsdk/model/key_capsule.py +10 -0
- huaweicloud_encryptionsdk/model/key_capsule_config.py +12 -0
- huaweicloud_encryptionsdk/model/kms_config.py +10 -0
- huaweicloud_encryptionsdk/model/request/__init__.py +0 -0
- huaweicloud_encryptionsdk/model/request/encrypt_request.py +10 -0
- huaweicloud_encryptionsdk/model/request/sign_request.py +2 -0
- huaweicloud_encryptionsdk/model/request/verify_request.py +2 -0
- huaweicloud_encryptionsdk/proof/__init__.py +0 -0
- huaweicloud_encryptionsdk/proof/attestation_document.py +36 -0
- huaweicloud_encryptionsdk/proof/collector/__init__.py +0 -0
- huaweicloud_encryptionsdk/proof/collector/cce_proof_collector.py +24 -0
- huaweicloud_encryptionsdk/proof/collector/ecs_proof_collector.py +11 -0
- huaweicloud_encryptionsdk/proof/collector/key_pair_proof_collector.py +55 -0
- huaweicloud_encryptionsdk/proof/collector/ma_proof_collector.py +51 -0
- huaweicloud_encryptionsdk/proof/private_key_decrypt_callback.py +7 -0
- huaweicloud_encryptionsdk/proof/proof_collector.py +11 -0
- huaweicloud_encryptionsdk/proof/proof_collector_factory.py +53 -0
- huaweicloud_encryptionsdk/proof/proof_info.py +10 -0
- huaweicloud_encryptionsdk/util/__init__.py +0 -0
- huaweicloud_encryptionsdk/util/common_utils.py +12 -0
- tests/__init__.py +0 -0
- tests/test_enums.py +84 -0
- tests/test_exceptions.py +38 -0
- tests/test_factories.py +71 -0
- tests/test_huawei_crypto.py +67 -0
- tests/test_imports.py +46 -0
- tests/test_kms_models.py +95 -0
- tests/test_log_file_backup.py +45 -0
- tests/test_lts_struct_log_builder.py +97 -0
- tests/test_models.py +142 -0
- tests/test_utils.py +111 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import random
|
|
3
|
+
|
|
4
|
+
from loguru import logger
|
|
5
|
+
|
|
6
|
+
from huaweicloud_encryptionsdk._lts_sdk.producer.core.producer import Producer
|
|
7
|
+
from huaweicloud_encryptionsdk._lts_sdk.producer.model import lts_store
|
|
8
|
+
from huaweicloud_encryptionsdk._lts_sdk.producer.model.config import Config
|
|
9
|
+
from huaweicloud_encryptionsdk._lts_sdk.utils import common
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def generate_random_str(str_len=16):
|
|
13
|
+
"""
|
|
14
|
+
生成一个指定长度的随机字符串
|
|
15
|
+
"""
|
|
16
|
+
random_str = ''
|
|
17
|
+
base_str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789'
|
|
18
|
+
length = len(base_str) - 1
|
|
19
|
+
for i in range(str_len):
|
|
20
|
+
random_str += base_str[random.randint(0, length)]
|
|
21
|
+
return random_str
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def send_log_single_producer(endpoint, ak, sk, region_id, project_id, group_id, stream_id, log_count, log_size):
|
|
25
|
+
log_num = log_count
|
|
26
|
+
config = Config()
|
|
27
|
+
config.endpoint = endpoint
|
|
28
|
+
config.access_key = ak
|
|
29
|
+
config.access_secret = sk
|
|
30
|
+
config.region_id = region_id
|
|
31
|
+
config.project_id = project_id
|
|
32
|
+
producer = Producer.init_producer(config)
|
|
33
|
+
producer.start_producer()
|
|
34
|
+
|
|
35
|
+
group_id = group_id
|
|
36
|
+
stream_id = stream_id
|
|
37
|
+
|
|
38
|
+
batch_num = 20
|
|
39
|
+
count = int(log_num/batch_num)
|
|
40
|
+
leave = log_num % batch_num
|
|
41
|
+
|
|
42
|
+
logger.info("send count is {}, leave is {}", count, leave)
|
|
43
|
+
|
|
44
|
+
log_content = generate_random_str(log_size)
|
|
45
|
+
labels = {"keyA": "valueA"}
|
|
46
|
+
log = []
|
|
47
|
+
for i in range(batch_num):
|
|
48
|
+
log.append(log_content)
|
|
49
|
+
log_p = lts_store.generate_log(log, labels)
|
|
50
|
+
|
|
51
|
+
begin_ms = common.current_time_ms()
|
|
52
|
+
for i in range(count):
|
|
53
|
+
producer.send_log(group_id, stream_id, log_p)
|
|
54
|
+
log.clear()
|
|
55
|
+
|
|
56
|
+
if leave > 0:
|
|
57
|
+
for i in range(leave):
|
|
58
|
+
log.append(log_content)
|
|
59
|
+
log_p = lts_store.generate_log(log, labels)
|
|
60
|
+
producer.send_log(group_id, stream_id, log_p)
|
|
61
|
+
end_ms = common.current_time_ms()
|
|
62
|
+
logger.info("end send log, cost [{}]ms", end_ms - begin_ms)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
if __name__ == '__main__':
|
|
66
|
+
parser = argparse.ArgumentParser(description='lts python sdk send log help tester information')
|
|
67
|
+
parser.add_argument('--endpoint', dest='endpoint', type=str, help='lts endpoint')
|
|
68
|
+
parser.add_argument('--ak', dest='ak', type=str, help='huaweicloud ak')
|
|
69
|
+
parser.add_argument('--sk', dest='sk', type=str, help='huaweicloud sk')
|
|
70
|
+
parser.add_argument('--region', dest='region', type=str, help='huaweicloud region')
|
|
71
|
+
parser.add_argument('--project_id', dest='project_id', type=str, help='huaweicloud project_id')
|
|
72
|
+
parser.add_argument('--group_id', dest='group_id', type=str, help='send log group_id')
|
|
73
|
+
parser.add_argument('--stream_id', dest='stream_id', type=str, help='send log stream_id')
|
|
74
|
+
parser.add_argument('--log_count', dest='log_count', type=int, help='send log log_count')
|
|
75
|
+
parser.add_argument('--log_size', dest='log_size', type=int, help='send log log_size(byte)')
|
|
76
|
+
args = parser.parse_args()
|
|
77
|
+
send_log_single_producer(args.endpoint, args.ak, args.sk, args.region, args.project_id, args.group_id, args.stream_id, args.log_count, args.log_size)
|
|
File without changes
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def solv_log(x):
|
|
6
|
+
n = 0
|
|
7
|
+
while True:
|
|
8
|
+
n += 1
|
|
9
|
+
x >>= 7
|
|
10
|
+
if x == 0:
|
|
11
|
+
break
|
|
12
|
+
return n
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _encode_obj(obj) -> dict:
|
|
16
|
+
obj_dict = {}
|
|
17
|
+
obj_dict.update(obj.__dict__)
|
|
18
|
+
return obj_dict
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def convert_obj2_json_str(obj):
|
|
22
|
+
if obj is None:
|
|
23
|
+
return ""
|
|
24
|
+
return json.dumps(obj, default=_encode_obj, indent=None, sort_keys=True)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def convert_json_str2_obj(json_str, objClass):
|
|
28
|
+
parse_data = json.loads(json_str.strip('\t\r\n'))
|
|
29
|
+
result = objClass()
|
|
30
|
+
result.__dict__ = parse_data
|
|
31
|
+
return result
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def convert_dict2_obj(parse_data, objClass):
|
|
35
|
+
result = objClass()
|
|
36
|
+
result.__dict__ = parse_data
|
|
37
|
+
return result
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def convert_json_str2_list_obj(json_str, objClass):
|
|
41
|
+
lists = json.loads(json_str.strip('\t\r\n'))
|
|
42
|
+
result = []
|
|
43
|
+
for each_item in lists:
|
|
44
|
+
result.append(convert_dict2_obj(each_item, objClass))
|
|
45
|
+
return result
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def current_time_ms() -> int:
|
|
49
|
+
return int((time.time() * 1000))
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def current_time_ns() -> int:
|
|
53
|
+
return time.time_ns()
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def sleep_ms(mill):
|
|
57
|
+
time.sleep(mill / 1000)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import threading
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class ReadWriteLock:
|
|
5
|
+
|
|
6
|
+
def __init__(self):
|
|
7
|
+
self._cond = threading.Condition(threading.Lock())
|
|
8
|
+
self._active_readers = 0
|
|
9
|
+
|
|
10
|
+
def acquire_read(self):
|
|
11
|
+
self._cond.acquire()
|
|
12
|
+
try:
|
|
13
|
+
self._active_readers += 1
|
|
14
|
+
finally:
|
|
15
|
+
self._cond.release()
|
|
16
|
+
|
|
17
|
+
def release_read(self):
|
|
18
|
+
self._cond.acquire()
|
|
19
|
+
try:
|
|
20
|
+
self._active_readers -= 1
|
|
21
|
+
if not self._active_readers:
|
|
22
|
+
self._cond.notify_all()
|
|
23
|
+
finally:
|
|
24
|
+
self._cond.release()
|
|
25
|
+
|
|
26
|
+
def acquire_write(self):
|
|
27
|
+
self._cond.acquire()
|
|
28
|
+
while self._active_readers > 0:
|
|
29
|
+
self._cond.wait()
|
|
30
|
+
|
|
31
|
+
def release_write(self):
|
|
32
|
+
self._cond.release()
|
|
File without changes
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from huaweicloud_encryptionsdk.model.data_key_materials import DataKeyMaterials
|
|
5
|
+
from huaweicloud_encryptionsdk.common.utils import add_prevent_overflow
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class UsageStatus:
|
|
9
|
+
|
|
10
|
+
def __init__(self, bytes_encrypt_count: int, message_encrypt_count: int):
|
|
11
|
+
self._bytes_encrypt_count = bytes_encrypt_count
|
|
12
|
+
self._message_encrypt_count = message_encrypt_count
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def bytes_encrypt_count(self) -> int:
|
|
16
|
+
return self._bytes_encrypt_count
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
def message_encrypt_count(self) -> int:
|
|
20
|
+
return self._message_encrypt_count
|
|
21
|
+
|
|
22
|
+
def add(self, other: "UsageStatus") -> "UsageStatus":
|
|
23
|
+
return UsageStatus(
|
|
24
|
+
add_prevent_overflow(self._bytes_encrypt_count, other._bytes_encrypt_count),
|
|
25
|
+
add_prevent_overflow(self._message_encrypt_count, other._message_encrypt_count),
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class EncryptCacheEntry(ABC):
|
|
30
|
+
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def get_usage_status(self) -> UsageStatus:
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
@abstractmethod
|
|
36
|
+
def get_data_key_materials(self) -> DataKeyMaterials:
|
|
37
|
+
pass
|
|
38
|
+
|
|
39
|
+
def invalidate(self) -> None:
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class DecryptCacheEntry(ABC):
|
|
44
|
+
|
|
45
|
+
@abstractmethod
|
|
46
|
+
def get_data_key_materials(self) -> DataKeyMaterials:
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
def invalidate(self) -> None:
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class DataKeyCache(ABC):
|
|
54
|
+
|
|
55
|
+
@abstractmethod
|
|
56
|
+
def get_entry_for_encrypt(self, cache_id: str, usage_status: UsageStatus) -> Optional[EncryptCacheEntry]:
|
|
57
|
+
pass
|
|
58
|
+
|
|
59
|
+
@abstractmethod
|
|
60
|
+
def put_entry_for_encrypt(self, cache_id: str, data_key_materials: DataKeyMaterials, initial_usage: UsageStatus) -> None:
|
|
61
|
+
pass
|
|
62
|
+
|
|
63
|
+
def put_entry_for_encrypt_with_ttl(self, cache_id: str, survive_time: int, data_key_materials: DataKeyMaterials, initial_usage: UsageStatus) -> None:
|
|
64
|
+
self.put_entry_for_encrypt(cache_id, data_key_materials, initial_usage)
|
|
65
|
+
|
|
66
|
+
@abstractmethod
|
|
67
|
+
def get_entry_for_decrypt(self, cache_id: str) -> Optional[DecryptCacheEntry]:
|
|
68
|
+
pass
|
|
69
|
+
|
|
70
|
+
@abstractmethod
|
|
71
|
+
def put_entry_for_decrypt(self, cache_id: str, data_key_materials: DataKeyMaterials) -> None:
|
|
72
|
+
pass
|
|
73
|
+
|
|
74
|
+
def put_entry_for_decrypt_with_ttl(self, cache_id: str, survive_time: int, data_key_materials: DataKeyMaterials) -> None:
|
|
75
|
+
self.put_entry_for_decrypt(cache_id, data_key_materials)
|
|
76
|
+
|
|
77
|
+
@abstractmethod
|
|
78
|
+
def set_survival_time(self, survival_time: int) -> None:
|
|
79
|
+
pass
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import time
|
|
2
|
+
import threading
|
|
3
|
+
from collections import OrderedDict
|
|
4
|
+
from typing import Optional, List
|
|
5
|
+
|
|
6
|
+
from huaweicloud_encryptionsdk.cache.data_key_cache import DataKeyCache, UsageStatus, EncryptCacheEntry, DecryptCacheEntry
|
|
7
|
+
from huaweicloud_encryptionsdk.model.data_key_materials import DataKeyMaterials
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class _BaseEntry:
|
|
11
|
+
|
|
12
|
+
def __init__(self, key: str, expire_timestamp: int, material: Optional[DataKeyMaterials] = None, usage_status: Optional[UsageStatus] = None):
|
|
13
|
+
self.key = key
|
|
14
|
+
self.expire_timestamp = expire_timestamp
|
|
15
|
+
self.create_timestamp = int(time.time() * 1000)
|
|
16
|
+
self.material = material
|
|
17
|
+
self.usage_status = usage_status
|
|
18
|
+
self._lock = threading.Lock()
|
|
19
|
+
|
|
20
|
+
def is_expired(self) -> bool:
|
|
21
|
+
return int(time.time() * 1000) > self.expire_timestamp
|
|
22
|
+
|
|
23
|
+
def add_usage_info(self, usage_status: UsageStatus) -> UsageStatus:
|
|
24
|
+
with self._lock:
|
|
25
|
+
self.usage_status = self.usage_status.add(usage_status)
|
|
26
|
+
return self.usage_status
|
|
27
|
+
|
|
28
|
+
def __lt__(self, other):
|
|
29
|
+
if self.expire_timestamp != other.expire_timestamp:
|
|
30
|
+
return self.expire_timestamp < other.expire_timestamp
|
|
31
|
+
return self.create_timestamp < other.create_timestamp
|
|
32
|
+
|
|
33
|
+
def __eq__(self, other):
|
|
34
|
+
if not isinstance(other, _BaseEntry):
|
|
35
|
+
return False
|
|
36
|
+
return (self.expire_timestamp == other.expire_timestamp
|
|
37
|
+
and self.create_timestamp == other.create_timestamp
|
|
38
|
+
and self.key == other.key)
|
|
39
|
+
|
|
40
|
+
def __hash__(self):
|
|
41
|
+
return hash((self.key, self.expire_timestamp, self.create_timestamp))
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class _EncryptionEntryExposed(EncryptCacheEntry):
|
|
45
|
+
|
|
46
|
+
def __init__(self, entry: _BaseEntry, usage_status: UsageStatus):
|
|
47
|
+
self._entry = entry
|
|
48
|
+
self._usage_status = usage_status
|
|
49
|
+
|
|
50
|
+
def get_usage_status(self) -> UsageStatus:
|
|
51
|
+
return self._usage_status
|
|
52
|
+
|
|
53
|
+
def get_data_key_materials(self) -> DataKeyMaterials:
|
|
54
|
+
return self._entry.material
|
|
55
|
+
|
|
56
|
+
def invalidate(self) -> None:
|
|
57
|
+
pass
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class _DecryptionEntry(_BaseEntry, DecryptCacheEntry):
|
|
61
|
+
|
|
62
|
+
def get_data_key_materials(self) -> DataKeyMaterials:
|
|
63
|
+
return self.material
|
|
64
|
+
|
|
65
|
+
def invalidate(self) -> None:
|
|
66
|
+
pass
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class LocalDataKeyCache(DataKeyCache):
|
|
70
|
+
|
|
71
|
+
DEFAULT_CAPACITY = 1 << 4
|
|
72
|
+
DEFAULT_TTL = 1000000
|
|
73
|
+
|
|
74
|
+
def __init__(self):
|
|
75
|
+
self._capacity = self.DEFAULT_CAPACITY
|
|
76
|
+
self._key_expire_time = self.DEFAULT_TTL
|
|
77
|
+
self._cache: OrderedDict[str, _BaseEntry] = OrderedDict()
|
|
78
|
+
self._tree_set: List[_BaseEntry] = []
|
|
79
|
+
self._lock = threading.Lock()
|
|
80
|
+
|
|
81
|
+
def set_capacity(self, capacity: int) -> None:
|
|
82
|
+
self._capacity = capacity
|
|
83
|
+
|
|
84
|
+
def get_entry_for_encrypt(self, cache_id: str, usage_status: UsageStatus) -> Optional[EncryptCacheEntry]:
|
|
85
|
+
entry = self._get_entry(cache_id)
|
|
86
|
+
if entry is None:
|
|
87
|
+
return None
|
|
88
|
+
if entry.is_expired():
|
|
89
|
+
self._remove_entry(entry)
|
|
90
|
+
return None
|
|
91
|
+
status = entry.add_usage_info(usage_status)
|
|
92
|
+
return _EncryptionEntryExposed(entry, status)
|
|
93
|
+
|
|
94
|
+
def put_entry_for_encrypt(self, cache_id: str, data_key_materials: DataKeyMaterials, initial_usage: UsageStatus) -> None:
|
|
95
|
+
base_entry = _BaseEntry(cache_id, self._key_expire_time + int(time.time() * 1000), data_key_materials, initial_usage)
|
|
96
|
+
self._put_entry(base_entry)
|
|
97
|
+
|
|
98
|
+
def put_entry_for_encrypt_with_ttl(self, cache_id: str, survive_time: int, data_key_materials: DataKeyMaterials, initial_usage: UsageStatus) -> None:
|
|
99
|
+
base_entry = _BaseEntry(cache_id, survive_time + int(time.time() * 1000), data_key_materials, initial_usage)
|
|
100
|
+
self._put_entry(base_entry)
|
|
101
|
+
|
|
102
|
+
def get_entry_for_decrypt(self, cache_id: str) -> Optional[DecryptCacheEntry]:
|
|
103
|
+
entry = self._get_entry(cache_id)
|
|
104
|
+
if entry is None:
|
|
105
|
+
return None
|
|
106
|
+
if entry.is_expired():
|
|
107
|
+
self._remove_entry(entry)
|
|
108
|
+
return None
|
|
109
|
+
return _DecryptionEntry(entry.key, entry.expire_timestamp, entry.material, entry.usage_status)
|
|
110
|
+
|
|
111
|
+
def put_entry_for_decrypt(self, cache_id: str, data_key_materials: DataKeyMaterials) -> None:
|
|
112
|
+
entry = _DecryptionEntry(cache_id, self._key_expire_time + int(time.time() * 1000), data_key_materials, None)
|
|
113
|
+
self._put_entry(entry)
|
|
114
|
+
|
|
115
|
+
def put_entry_for_decrypt_with_ttl(self, cache_id: str, survive_time: int, data_key_materials: DataKeyMaterials) -> None:
|
|
116
|
+
entry = _DecryptionEntry(cache_id, survive_time + int(time.time() * 1000), data_key_materials, None)
|
|
117
|
+
self._put_entry(entry)
|
|
118
|
+
|
|
119
|
+
def set_survival_time(self, survival_time: int) -> None:
|
|
120
|
+
self._key_expire_time = survival_time
|
|
121
|
+
|
|
122
|
+
def _get_entry(self, key: str) -> Optional[_BaseEntry]:
|
|
123
|
+
with self._lock:
|
|
124
|
+
entry = self._cache.get(key)
|
|
125
|
+
if entry is not None:
|
|
126
|
+
self._cache.move_to_end(key)
|
|
127
|
+
return entry
|
|
128
|
+
|
|
129
|
+
def _remove_entry(self, entry: _BaseEntry) -> None:
|
|
130
|
+
with self._lock:
|
|
131
|
+
self._cache.pop(entry.key, None)
|
|
132
|
+
try:
|
|
133
|
+
self._tree_set.remove(entry)
|
|
134
|
+
except ValueError:
|
|
135
|
+
pass
|
|
136
|
+
|
|
137
|
+
def _put_entry(self, entry: _BaseEntry) -> None:
|
|
138
|
+
with self._lock:
|
|
139
|
+
old_entry = self._cache.pop(entry.key, None)
|
|
140
|
+
if old_entry is not None:
|
|
141
|
+
try:
|
|
142
|
+
self._tree_set.remove(old_entry)
|
|
143
|
+
except ValueError:
|
|
144
|
+
pass
|
|
145
|
+
self._cache[entry.key] = entry
|
|
146
|
+
self._tree_set.append(entry)
|
|
147
|
+
self._tree_set.sort()
|
|
148
|
+
now = int(time.time() * 1000)
|
|
149
|
+
while self._tree_set and self._tree_set[0].expire_timestamp < now:
|
|
150
|
+
expired = self._tree_set.pop(0)
|
|
151
|
+
self._cache.pop(expired.key, None)
|
|
152
|
+
self._check_capacity()
|
|
153
|
+
|
|
154
|
+
def _check_capacity(self) -> None:
|
|
155
|
+
while len(self._cache) > self._capacity:
|
|
156
|
+
oldest_key = next(iter(self._cache))
|
|
157
|
+
old_entry = self._cache.pop(oldest_key)
|
|
158
|
+
try:
|
|
159
|
+
self._tree_set.remove(old_entry)
|
|
160
|
+
except ValueError:
|
|
161
|
+
pass
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class Constants:
|
|
2
|
+
KEY_SPEC_DELIMITER = "_"
|
|
3
|
+
NUM_0 = 0
|
|
4
|
+
NUM_1 = 1
|
|
5
|
+
BLOCK_SIZE = 1024 * 256
|
|
6
|
+
VERSION = 1
|
|
7
|
+
VERSION_2 = 2
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
KEY_SPEC_DELIMITER = Constants.KEY_SPEC_DELIMITER
|
|
11
|
+
NUM_0 = Constants.NUM_0
|
|
12
|
+
NUM_1 = Constants.NUM_1
|
|
13
|
+
BLOCK_SIZE = Constants.BLOCK_SIZE
|
|
14
|
+
VERSION = Constants.VERSION
|
|
15
|
+
VERSION_2 = Constants.VERSION_2
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
class CountingOutputStream:
|
|
2
|
+
|
|
3
|
+
def __init__(self, output_stream):
|
|
4
|
+
self._output_stream = output_stream
|
|
5
|
+
self._bytes_written = 0
|
|
6
|
+
|
|
7
|
+
def write(self, data):
|
|
8
|
+
if isinstance(data, str):
|
|
9
|
+
data = data.encode('utf-8')
|
|
10
|
+
self._output_stream.write(data)
|
|
11
|
+
self._bytes_written += len(data)
|
|
12
|
+
|
|
13
|
+
def get_bytes_written(self):
|
|
14
|
+
return self._bytes_written
|
|
15
|
+
|
|
16
|
+
@property
|
|
17
|
+
def output_stream(self):
|
|
18
|
+
return self._output_stream
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import hashlib
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class CryptoFactory:
|
|
5
|
+
|
|
6
|
+
@staticmethod
|
|
7
|
+
def get_cipher(algorithm):
|
|
8
|
+
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
|
9
|
+
parts = algorithm.split("/")
|
|
10
|
+
alg_name = parts[0]
|
|
11
|
+
mode_name = parts[1] if len(parts) > 1 else ""
|
|
12
|
+
return alg_name, mode_name
|
|
13
|
+
|
|
14
|
+
@staticmethod
|
|
15
|
+
def get_message_digest(algorithm):
|
|
16
|
+
if algorithm is None:
|
|
17
|
+
raise ValueError('algorithm must not be None')
|
|
18
|
+
if CryptoFactory.is_sm_algorithm(algorithm):
|
|
19
|
+
try:
|
|
20
|
+
from gmssl import sm3
|
|
21
|
+
return SM3Digest()
|
|
22
|
+
except ImportError:
|
|
23
|
+
raise ValueError('SM3 algorithm requires gmssl library. Install with: pip install gmssl')
|
|
24
|
+
return hashlib.new(algorithm)
|
|
25
|
+
|
|
26
|
+
@staticmethod
|
|
27
|
+
def is_sm_algorithm(algorithm):
|
|
28
|
+
return algorithm is not None and "SM" in algorithm.upper()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class SM3Digest:
|
|
32
|
+
|
|
33
|
+
def __init__(self):
|
|
34
|
+
from gmssl import sm3 as _sm3
|
|
35
|
+
self._sm3 = _sm3
|
|
36
|
+
self._data = bytearray()
|
|
37
|
+
|
|
38
|
+
def update(self, data):
|
|
39
|
+
self._data.extend(data)
|
|
40
|
+
|
|
41
|
+
def digest(self):
|
|
42
|
+
from gmssl import sm3 as _sm3, func
|
|
43
|
+
result = _sm3.sm3_hash(list(self._data))
|
|
44
|
+
return bytes.fromhex(result)
|
|
45
|
+
|
|
46
|
+
def hexdigest(self):
|
|
47
|
+
from gmssl import sm3 as _sm3
|
|
48
|
+
return _sm3.sm3_hash(list(self._data))
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
|
|
3
|
+
from cryptography.hazmat.primitives.serialization import (
|
|
4
|
+
load_pem_private_key,
|
|
5
|
+
load_der_private_key,
|
|
6
|
+
)
|
|
7
|
+
from cryptography.hazmat.backends import default_backend
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ECPrivateKeyLoader:
|
|
11
|
+
|
|
12
|
+
@staticmethod
|
|
13
|
+
def load(key_content):
|
|
14
|
+
if key_content.strip().startswith('-----BEGIN'):
|
|
15
|
+
try:
|
|
16
|
+
return ECPrivateKeyLoader.load_pem(key_content)
|
|
17
|
+
except Exception as e:
|
|
18
|
+
raise Exception("access point key exception") from e
|
|
19
|
+
try:
|
|
20
|
+
der = base64.b64decode(key_content)
|
|
21
|
+
return ECPrivateKeyLoader.load_der(der)
|
|
22
|
+
except Exception as e:
|
|
23
|
+
raise Exception("access point key exception") from e
|
|
24
|
+
|
|
25
|
+
@staticmethod
|
|
26
|
+
def load_pem(pem):
|
|
27
|
+
try:
|
|
28
|
+
private_key = load_pem_private_key(
|
|
29
|
+
pem.encode("utf-8"), password=None, backend=default_backend()
|
|
30
|
+
)
|
|
31
|
+
return private_key
|
|
32
|
+
except Exception as e:
|
|
33
|
+
raise Exception("access point key exception") from e
|
|
34
|
+
|
|
35
|
+
@staticmethod
|
|
36
|
+
def load_der(der):
|
|
37
|
+
try:
|
|
38
|
+
private_key = load_der_private_key(
|
|
39
|
+
der, password=None, backend=default_backend()
|
|
40
|
+
)
|
|
41
|
+
return private_key
|
|
42
|
+
except Exception as e:
|
|
43
|
+
raise Exception("access point key exception") from e
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import requests
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class EcsMetadataService:
|
|
6
|
+
|
|
7
|
+
METADATA_BASE = "http://169.254.169.254/meta-data/latest/instance-identity"
|
|
8
|
+
DOCUMENT_URL = METADATA_BASE + "/document"
|
|
9
|
+
SIGNATURE_URL = METADATA_BASE + "/signature"
|
|
10
|
+
|
|
11
|
+
_cached_instance_id = None
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def get_ecs_instance_id(cls):
|
|
15
|
+
if cls._cached_instance_id is not None:
|
|
16
|
+
return cls._cached_instance_id
|
|
17
|
+
try:
|
|
18
|
+
doc_str = cls.fetch_identity_document()
|
|
19
|
+
if doc_str is None:
|
|
20
|
+
return None
|
|
21
|
+
doc = json.loads(doc_str)
|
|
22
|
+
cls._cached_instance_id = doc.get("id")
|
|
23
|
+
return cls._cached_instance_id
|
|
24
|
+
except (json.JSONDecodeError, requests.exceptions.RequestException):
|
|
25
|
+
return None
|
|
26
|
+
|
|
27
|
+
@classmethod
|
|
28
|
+
def fetch_identity_document(cls):
|
|
29
|
+
return cls._fetch_metadata(cls.DOCUMENT_URL)
|
|
30
|
+
|
|
31
|
+
@classmethod
|
|
32
|
+
def fetch_identity_signature(cls):
|
|
33
|
+
return cls._fetch_metadata(cls.SIGNATURE_URL)
|
|
34
|
+
|
|
35
|
+
@classmethod
|
|
36
|
+
def _fetch_metadata(cls, url):
|
|
37
|
+
try:
|
|
38
|
+
resp = requests.get(url, timeout=5)
|
|
39
|
+
resp.raise_for_status()
|
|
40
|
+
return resp.text
|
|
41
|
+
except Exception:
|
|
42
|
+
return None
|