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,75 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class CryptoAlgorithm(Enum):
|
|
5
|
+
|
|
6
|
+
AES_128_GCM_NOPADDING = ("AES_128", "AES/GCM/NoPadding", 16, 12, 16, 16, 1, 1, "AES", 128)
|
|
7
|
+
AES_256_GCM_NOPADDING = ("AES_256", "AES/GCM/NoPadding", 32, 12, 16, 16, 2, 1, "AES", 256)
|
|
8
|
+
SM4_128_GCM_NOPADDING = ("SM4_128", "SM4/GCM/NoPadding", 16, 12, 16, 16, 3, 1, "SM4", 128)
|
|
9
|
+
SM4_128_CBC_PADDING = ("SM4_128", "SM4/CBC/PKCS5Padding", 16, 16, 16, 16, 4, 1, "SM4", 128)
|
|
10
|
+
|
|
11
|
+
def __init__(self, key_spec, crypto_alg, key_len, iv_len, tag_len, block_size, value, version, sec_key_algorithm, datakey_length):
|
|
12
|
+
self._key_spec = key_spec
|
|
13
|
+
self._crypto_alg = crypto_alg
|
|
14
|
+
self._key_len = key_len
|
|
15
|
+
self._iv_len = iv_len
|
|
16
|
+
self._tag_len = tag_len
|
|
17
|
+
self._block_size = block_size
|
|
18
|
+
self._value = value
|
|
19
|
+
self._version = version
|
|
20
|
+
self._sec_key_algorithm = sec_key_algorithm
|
|
21
|
+
self._datakey_length = datakey_length
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def key_spec(self):
|
|
25
|
+
return self._key_spec
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
def crypto_alg(self):
|
|
29
|
+
return self._crypto_alg
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def key_len(self):
|
|
33
|
+
return self._key_len
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def iv_len(self):
|
|
37
|
+
return self._iv_len
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def tag_len(self):
|
|
41
|
+
return self._tag_len
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def block_size(self):
|
|
45
|
+
return self._block_size
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def value(self):
|
|
49
|
+
return self._value
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def version(self):
|
|
53
|
+
return self._version
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def sec_key_algorithm(self):
|
|
57
|
+
return self._sec_key_algorithm
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def datakey_length(self):
|
|
61
|
+
return self._datakey_length
|
|
62
|
+
|
|
63
|
+
@classmethod
|
|
64
|
+
def get_algorithm(cls, algorithm_value):
|
|
65
|
+
for algorithm in cls:
|
|
66
|
+
if algorithm.value == algorithm_value:
|
|
67
|
+
return algorithm
|
|
68
|
+
return None
|
|
69
|
+
|
|
70
|
+
def get_algorithm_name(self):
|
|
71
|
+
return self._key_spec.split("_")[0]
|
|
72
|
+
|
|
73
|
+
def get_crypto_mode(self):
|
|
74
|
+
parts = self._crypto_alg.split("/")
|
|
75
|
+
return parts[1]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class DataKeyGenerateType(Enum):
|
|
5
|
+
|
|
6
|
+
LOCAL_GENERATE = ("create data key from local", 1)
|
|
7
|
+
KMS_GENERATE = ("create data key from KMS", 2)
|
|
8
|
+
KEY_CAPSULE_GENERATE = ("create data key from key capsule", 3)
|
|
9
|
+
|
|
10
|
+
def __init__(self, desc, code):
|
|
11
|
+
self._desc = desc
|
|
12
|
+
self._code = code
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def desc(self):
|
|
16
|
+
return self._desc
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
def code(self):
|
|
20
|
+
return self._code
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class KeyProviderEnum(Enum):
|
|
5
|
+
|
|
6
|
+
LOCAL_PROVIDER = (1, "huawei-local")
|
|
7
|
+
KMS_PROVIDER = (2, "huawei-kms")
|
|
8
|
+
|
|
9
|
+
def __init__(self, code, name):
|
|
10
|
+
self._code = code
|
|
11
|
+
self._name = name
|
|
12
|
+
|
|
13
|
+
@property
|
|
14
|
+
def code(self):
|
|
15
|
+
return self._code
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def name(self):
|
|
19
|
+
return self._name
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class KeyringTypeEnum(Enum):
|
|
5
|
+
|
|
6
|
+
RAW_AES = "AES"
|
|
7
|
+
RAW_SM2 = "SM2"
|
|
8
|
+
RAW_RSA = "RSA"
|
|
9
|
+
RAW_SM4_CBC = "SM4_CBC"
|
|
10
|
+
RAW_SM4_GCM = "SM4_GCM"
|
|
11
|
+
KMS_MULTI_REGION = "multi"
|
|
12
|
+
KMS_DISCOVERY = "discovery"
|
|
13
|
+
KMS_KEY_CAPSULE = "key_capsule"
|
|
14
|
+
|
|
15
|
+
def __init__(self, type_value):
|
|
16
|
+
self._type = type_value
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
def type(self):
|
|
20
|
+
return self._type
|
|
21
|
+
|
|
22
|
+
@classmethod
|
|
23
|
+
def get_raw_keyring_type(cls, type_str):
|
|
24
|
+
for keyring_type in cls:
|
|
25
|
+
if keyring_type.type.lower() == type_str.lower():
|
|
26
|
+
return keyring_type
|
|
27
|
+
return None
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from huaweicloud_encryptionsdk.model.access_point_config import AccessPointConfig
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class KeyCapsuleConfig:
|
|
9
|
+
region: str = ""
|
|
10
|
+
default_policy_id: Optional[str] = None
|
|
11
|
+
default_key_policy: Optional[str] = None
|
|
12
|
+
access_point_config: Optional[AccessPointConfig] = None
|
|
File without changes
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from typing import Dict, Optional
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@dataclass
|
|
6
|
+
class EncryptRequest:
|
|
7
|
+
encryption_context: Dict[str, str] = field(default_factory=dict)
|
|
8
|
+
plain_text: bytes = b""
|
|
9
|
+
policy_id: Optional[str] = None
|
|
10
|
+
key_policy: Optional[str] = None
|
|
File without changes
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from dataclasses import dataclass, field, asdict
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@dataclass
|
|
7
|
+
class AttestationDocument:
|
|
8
|
+
ecs_signature: Optional[str] = field(default=None)
|
|
9
|
+
custom_signature: Optional[str] = field(default=None)
|
|
10
|
+
custom_public_key: Optional[str] = field(default=None)
|
|
11
|
+
expire_time: Optional[str] = field(default=None)
|
|
12
|
+
service_token: Optional[str] = field(default=None)
|
|
13
|
+
modelarts_job_id: Optional[str] = field(default=None)
|
|
14
|
+
modelarts_pool_id: Optional[str] = field(default=None)
|
|
15
|
+
|
|
16
|
+
def to_dict(self) -> dict:
|
|
17
|
+
return {k: v for k, v in asdict(self).items() if v is not None}
|
|
18
|
+
|
|
19
|
+
def to_json(self) -> str:
|
|
20
|
+
return json.dumps(self.to_dict())
|
|
21
|
+
|
|
22
|
+
@classmethod
|
|
23
|
+
def from_dict(cls, data: dict) -> "AttestationDocument":
|
|
24
|
+
return cls(
|
|
25
|
+
ecs_signature=data.get("ecs_signature"),
|
|
26
|
+
custom_signature=data.get("custom_signature"),
|
|
27
|
+
custom_public_key=data.get("custom_public_key"),
|
|
28
|
+
expire_time=data.get("expire_time"),
|
|
29
|
+
service_token=data.get("service_token"),
|
|
30
|
+
modelarts_job_id=data.get("modelarts_job_id"),
|
|
31
|
+
modelarts_pool_id=data.get("modelarts_pool_id"),
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
@classmethod
|
|
35
|
+
def from_json(cls, json_str: str) -> "AttestationDocument":
|
|
36
|
+
return cls.from_dict(json.loads(json_str))
|
|
File without changes
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from huaweicloud_encryptionsdk.exception.errors import HuaweicloudException
|
|
2
|
+
from huaweicloud_encryptionsdk.proof.attestation_document import AttestationDocument
|
|
3
|
+
from huaweicloud_encryptionsdk.proof.proof_collector import ProofCollector
|
|
4
|
+
from huaweicloud_encryptionsdk.proof.proof_info import ProofInfo
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
SERVICE_ACCOUNT_TOKEN_PATH = "/var/run/secrets/kubernetes.io/serviceaccount/token"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class CceProofCollector(ProofCollector):
|
|
11
|
+
|
|
12
|
+
def collect(self, proof_info: ProofInfo) -> AttestationDocument:
|
|
13
|
+
service_token = self._read_service_account_token()
|
|
14
|
+
return AttestationDocument(service_token=service_token)
|
|
15
|
+
|
|
16
|
+
@staticmethod
|
|
17
|
+
def _read_service_account_token() -> str:
|
|
18
|
+
try:
|
|
19
|
+
with open(SERVICE_ACCOUNT_TOKEN_PATH, "r") as f:
|
|
20
|
+
return f.read().strip()
|
|
21
|
+
except Exception as e:
|
|
22
|
+
raise HuaweicloudException(
|
|
23
|
+
f"Failed to read CCE service account token from {SERVICE_ACCOUNT_TOKEN_PATH}", e
|
|
24
|
+
)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from huaweicloud_encryptionsdk.common.ecs_metadata_service import EcsMetadataService
|
|
2
|
+
from huaweicloud_encryptionsdk.proof.attestation_document import AttestationDocument
|
|
3
|
+
from huaweicloud_encryptionsdk.proof.proof_collector import ProofCollector
|
|
4
|
+
from huaweicloud_encryptionsdk.proof.proof_info import ProofInfo
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class EcsProofCollector(ProofCollector):
|
|
8
|
+
|
|
9
|
+
def collect(self, proof_info: ProofInfo) -> AttestationDocument:
|
|
10
|
+
signature = EcsMetadataService.fetch_identity_signature()
|
|
11
|
+
return AttestationDocument(ecs_signature=signature)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
from datetime import datetime, timezone, timedelta
|
|
3
|
+
|
|
4
|
+
from cryptography.hazmat.primitives.asymmetric import ec, utils as ec_utils
|
|
5
|
+
from cryptography.hazmat.primitives import hashes, serialization
|
|
6
|
+
|
|
7
|
+
from huaweicloud_encryptionsdk.exception.errors import HuaweicloudException, ErrorMessage
|
|
8
|
+
from huaweicloud_encryptionsdk.proof.attestation_document import AttestationDocument
|
|
9
|
+
from huaweicloud_encryptionsdk.proof.proof_collector import ProofCollector
|
|
10
|
+
from huaweicloud_encryptionsdk.proof.proof_info import ProofInfo
|
|
11
|
+
from huaweicloud_encryptionsdk.common.ec_private_key_loader import ECPrivateKeyLoader
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class KeyPairProofCollector(ProofCollector):
|
|
15
|
+
|
|
16
|
+
def collect(self, proof_info: ProofInfo) -> AttestationDocument:
|
|
17
|
+
private_key_str = proof_info.private_key_decrypt_callback(proof_info.encrypted_private_key)
|
|
18
|
+
private_key = ECPrivateKeyLoader.load(private_key_str)
|
|
19
|
+
expire_time = self._get_expire_time()
|
|
20
|
+
origin_text = (proof_info.key_capsule or "") + expire_time
|
|
21
|
+
signature = self._get_signature(private_key, origin_text)
|
|
22
|
+
return AttestationDocument(
|
|
23
|
+
custom_public_key=self._get_public_key_from_private_key(private_key),
|
|
24
|
+
custom_signature=signature,
|
|
25
|
+
expire_time=expire_time,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
@staticmethod
|
|
29
|
+
def _get_public_key_from_private_key(private_key) -> str:
|
|
30
|
+
try:
|
|
31
|
+
public_key = private_key.public_key()
|
|
32
|
+
public_der = public_key.public_bytes(
|
|
33
|
+
encoding=serialization.Encoding.DER,
|
|
34
|
+
format=serialization.PublicFormat.SubjectPublicKeyInfo,
|
|
35
|
+
)
|
|
36
|
+
return base64.b64encode(public_der).decode("utf-8")
|
|
37
|
+
except Exception as e:
|
|
38
|
+
raise HuaweicloudException(ErrorMessage.GET_PUB_KEY_EXCEPTION.message, e)
|
|
39
|
+
|
|
40
|
+
@staticmethod
|
|
41
|
+
def _get_signature(private_key, origin_text: str) -> str:
|
|
42
|
+
try:
|
|
43
|
+
signature_bytes = private_key.sign(
|
|
44
|
+
origin_text.encode("utf-8"),
|
|
45
|
+
ec.ECDSA(hashes.SHA256()),
|
|
46
|
+
)
|
|
47
|
+
return base64.b64encode(signature_bytes).decode("utf-8")
|
|
48
|
+
except Exception as e:
|
|
49
|
+
raise HuaweicloudException(ErrorMessage.COLLECT_PROOF_EXCEPTION.message, e)
|
|
50
|
+
|
|
51
|
+
@staticmethod
|
|
52
|
+
def _get_expire_time() -> str:
|
|
53
|
+
expire = datetime.now(timezone.utc) + timedelta(minutes=30)
|
|
54
|
+
expire = expire.replace(microsecond=0)
|
|
55
|
+
return expire.isoformat().replace("+00:00", "Z")
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from huaweicloud_encryptionsdk.exception.errors import HuaweicloudException
|
|
4
|
+
from huaweicloud_encryptionsdk.proof.attestation_document import AttestationDocument
|
|
5
|
+
from huaweicloud_encryptionsdk.proof.proof_collector import ProofCollector
|
|
6
|
+
from huaweicloud_encryptionsdk.proof.proof_info import ProofInfo
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
LWS_LEADER_ADDRESS_ENV = "LWS_LEADER_ADDRESS"
|
|
10
|
+
MA_JOB_NAME_ENV = "MA_JOB_NAME"
|
|
11
|
+
MODELARTS_PREFIX = "modelarts-"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class MaProofCollector(ProofCollector):
|
|
15
|
+
"""ModelArts (MA) 接入点证明收集器。
|
|
16
|
+
|
|
17
|
+
根据环境变量自动判断场景:
|
|
18
|
+
- 推理场景:读 LWS_LEADER_ADDRESS,按 . 分割取最后一段作为 pool_id
|
|
19
|
+
- 训练场景:读 MA_JOB_NAME,去掉前缀 modelarts- 得到 job_id
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def collect(self, proof_info: ProofInfo) -> AttestationDocument:
|
|
23
|
+
pool_id = self._extract_pool_id()
|
|
24
|
+
job_id = self._extract_job_id()
|
|
25
|
+
|
|
26
|
+
if pool_id is None and job_id is None:
|
|
27
|
+
raise HuaweicloudException(
|
|
28
|
+
f"Failed to collect MA proof: neither {LWS_LEADER_ADDRESS_ENV} "
|
|
29
|
+
f"nor {MA_JOB_NAME_ENV} found"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
return AttestationDocument(
|
|
33
|
+
modelarts_pool_id=pool_id,
|
|
34
|
+
modelarts_job_id=job_id,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
@staticmethod
|
|
38
|
+
def _extract_pool_id() -> str | None:
|
|
39
|
+
addr = os.environ.get(LWS_LEADER_ADDRESS_ENV, "")
|
|
40
|
+
if not addr:
|
|
41
|
+
return None
|
|
42
|
+
return addr.split(".")[-1]
|
|
43
|
+
|
|
44
|
+
@staticmethod
|
|
45
|
+
def _extract_job_id() -> str | None:
|
|
46
|
+
job_name = os.environ.get(MA_JOB_NAME_ENV, "")
|
|
47
|
+
if not job_name:
|
|
48
|
+
return None
|
|
49
|
+
if job_name.startswith(MODELARTS_PREFIX):
|
|
50
|
+
return job_name[len(MODELARTS_PREFIX):]
|
|
51
|
+
return job_name
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
|
|
3
|
+
from huaweicloud_encryptionsdk.proof.proof_info import ProofInfo
|
|
4
|
+
from huaweicloud_encryptionsdk.proof.attestation_document import AttestationDocument
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ProofCollector(ABC):
|
|
8
|
+
|
|
9
|
+
@abstractmethod
|
|
10
|
+
def collect(self, proof_info: ProofInfo) -> AttestationDocument:
|
|
11
|
+
pass
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import threading
|
|
2
|
+
from typing import Dict, Optional
|
|
3
|
+
|
|
4
|
+
from huaweicloud_encryptionsdk.proof.proof_collector import ProofCollector
|
|
5
|
+
from huaweicloud_encryptionsdk.proof.proof_info import ProofInfo
|
|
6
|
+
from huaweicloud_encryptionsdk.proof.attestation_document import AttestationDocument
|
|
7
|
+
from huaweicloud_encryptionsdk.proof.collector.ecs_proof_collector import EcsProofCollector
|
|
8
|
+
from huaweicloud_encryptionsdk.proof.collector.key_pair_proof_collector import KeyPairProofCollector
|
|
9
|
+
from huaweicloud_encryptionsdk.proof.collector.cce_proof_collector import CceProofCollector
|
|
10
|
+
from huaweicloud_encryptionsdk.proof.collector.ma_proof_collector import MaProofCollector
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ProofCollectorFactory:
|
|
14
|
+
|
|
15
|
+
_COLLECTORS: Dict[int, ProofCollector] = {}
|
|
16
|
+
_lock = threading.Lock()
|
|
17
|
+
|
|
18
|
+
@classmethod
|
|
19
|
+
def _init_collectors(cls):
|
|
20
|
+
if not cls._COLLECTORS:
|
|
21
|
+
with cls._lock:
|
|
22
|
+
if not cls._COLLECTORS:
|
|
23
|
+
cls._COLLECTORS[1] = EcsProofCollector()
|
|
24
|
+
cls._COLLECTORS[2] = KeyPairProofCollector()
|
|
25
|
+
cls._COLLECTORS[3] = CceProofCollector()
|
|
26
|
+
cls._COLLECTORS[4] = MaProofCollector()
|
|
27
|
+
|
|
28
|
+
@classmethod
|
|
29
|
+
def register_collector(cls, type_val: int, collector: ProofCollector) -> None:
|
|
30
|
+
if collector is None:
|
|
31
|
+
raise ValueError("Type and collector cannot be null")
|
|
32
|
+
with cls._lock:
|
|
33
|
+
cls._COLLECTORS[type_val] = collector
|
|
34
|
+
|
|
35
|
+
@classmethod
|
|
36
|
+
def get_collector(cls, type_val: int) -> ProofCollector:
|
|
37
|
+
cls._init_collectors()
|
|
38
|
+
if type_val is None:
|
|
39
|
+
raise ValueError("Access point type cannot be null")
|
|
40
|
+
collector = cls._COLLECTORS.get(type_val)
|
|
41
|
+
if collector is None:
|
|
42
|
+
raise ValueError(
|
|
43
|
+
f"Unsupported access point type: {type_val}. Supported types: {list(cls._COLLECTORS.keys())}"
|
|
44
|
+
)
|
|
45
|
+
return collector
|
|
46
|
+
|
|
47
|
+
@classmethod
|
|
48
|
+
def collect(cls, proof_info: ProofInfo) -> AttestationDocument:
|
|
49
|
+
if proof_info is None:
|
|
50
|
+
raise ValueError("AccessPointConfig cannot be null")
|
|
51
|
+
type_val = proof_info.type
|
|
52
|
+
collector = cls.get_collector(type_val)
|
|
53
|
+
return collector.collect(proof_info)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Callable, Optional
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@dataclass
|
|
6
|
+
class ProofInfo:
|
|
7
|
+
type: int = 0
|
|
8
|
+
encrypted_private_key: Optional[str] = None
|
|
9
|
+
private_key_decrypt_callback: Optional[Callable[[str], str]] = None
|
|
10
|
+
key_capsule: Optional[str] = None
|
|
File without changes
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from typing import Dict
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class CommonUtils:
|
|
5
|
+
|
|
6
|
+
@staticmethod
|
|
7
|
+
def get_encrypt_map() -> Dict[str, str]:
|
|
8
|
+
return {"key": "value", "context": "encrypt"}
|
|
9
|
+
|
|
10
|
+
@staticmethod
|
|
11
|
+
def get_encryption_context() -> Dict[str, str]:
|
|
12
|
+
return {"encryption": "context", "simple": "test", "caching": "encrypt"}
|
tests/__init__.py
ADDED
|
File without changes
|
tests/test_enums.py
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from huaweicloud_encryptionsdk.model.enums.crypto_algorithm import CryptoAlgorithm
|
|
3
|
+
from huaweicloud_encryptionsdk.model.enums.access_point_type import AccessPointType
|
|
4
|
+
from huaweicloud_encryptionsdk.model.enums.key_provider_enum import KeyProviderEnum
|
|
5
|
+
from huaweicloud_encryptionsdk.model.enums.data_key_generate_type import DataKeyGenerateType
|
|
6
|
+
from huaweicloud_encryptionsdk.model.enums.keyring_type_enum import KeyringTypeEnum
|
|
7
|
+
from huaweicloud_encryptionsdk.exception.errors import ErrorMessage
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TestCryptoAlgorithm:
|
|
11
|
+
def test_all_values(self):
|
|
12
|
+
assert CryptoAlgorithm.AES_128_GCM_NOPADDING.value == 1
|
|
13
|
+
assert CryptoAlgorithm.AES_256_GCM_NOPADDING.value == 2
|
|
14
|
+
assert CryptoAlgorithm.SM4_128_GCM_NOPADDING.value == 3
|
|
15
|
+
assert CryptoAlgorithm.SM4_128_CBC_PADDING.value == 4
|
|
16
|
+
|
|
17
|
+
def test_key_lengths(self):
|
|
18
|
+
assert CryptoAlgorithm.AES_128_GCM_NOPADDING.key_len == 16
|
|
19
|
+
assert CryptoAlgorithm.AES_256_GCM_NOPADDING.key_len == 32
|
|
20
|
+
assert CryptoAlgorithm.SM4_128_GCM_NOPADDING.key_len == 16
|
|
21
|
+
|
|
22
|
+
def test_get_algorithm(self):
|
|
23
|
+
assert CryptoAlgorithm.get_algorithm(1) == CryptoAlgorithm.AES_128_GCM_NOPADDING
|
|
24
|
+
assert CryptoAlgorithm.get_algorithm(2) == CryptoAlgorithm.AES_256_GCM_NOPADDING
|
|
25
|
+
assert CryptoAlgorithm.get_algorithm(3) == CryptoAlgorithm.SM4_128_GCM_NOPADDING
|
|
26
|
+
assert CryptoAlgorithm.get_algorithm(4) == CryptoAlgorithm.SM4_128_CBC_PADDING
|
|
27
|
+
|
|
28
|
+
def test_get_algorithm_name(self):
|
|
29
|
+
assert "AES" in CryptoAlgorithm.AES_256_GCM_NOPADDING.get_algorithm_name() or "GCM" in CryptoAlgorithm.AES_256_GCM_NOPADDING.get_algorithm_name()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class TestAccessPointType:
|
|
33
|
+
def test_all_values(self):
|
|
34
|
+
assert AccessPointType.ECS.code == 1
|
|
35
|
+
assert AccessPointType.CUSTOM.code == 2
|
|
36
|
+
assert AccessPointType.CCE.code == 3
|
|
37
|
+
|
|
38
|
+
def test_display_names(self):
|
|
39
|
+
assert AccessPointType.ECS.display_name == "ECS"
|
|
40
|
+
assert AccessPointType.CUSTOM.display_name == "Custom"
|
|
41
|
+
assert AccessPointType.CCE.display_name == "CCE"
|
|
42
|
+
|
|
43
|
+
def test_get_display_name_by_code(self):
|
|
44
|
+
assert AccessPointType.get_display_name_by_code(1) == "ECS"
|
|
45
|
+
assert AccessPointType.get_display_name_by_code(2) == "Custom"
|
|
46
|
+
assert AccessPointType.get_display_name_by_code(3) == "CCE"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class TestKeyProviderEnum:
|
|
50
|
+
def test_all_values(self):
|
|
51
|
+
assert KeyProviderEnum.LOCAL_PROVIDER.code == 1
|
|
52
|
+
assert KeyProviderEnum.KMS_PROVIDER.code == 2
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class TestDataKeyGenerateType:
|
|
56
|
+
def test_all_values(self):
|
|
57
|
+
assert DataKeyGenerateType.LOCAL_GENERATE.code == 1
|
|
58
|
+
assert DataKeyGenerateType.KMS_GENERATE.code == 2
|
|
59
|
+
assert DataKeyGenerateType.KEY_CAPSULE_GENERATE.code == 3
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class TestKeyringTypeEnum:
|
|
63
|
+
def test_all_values(self):
|
|
64
|
+
assert KeyringTypeEnum.RAW_AES.type == "AES"
|
|
65
|
+
assert KeyringTypeEnum.RAW_SM2.type == "SM2"
|
|
66
|
+
assert KeyringTypeEnum.RAW_RSA.type == "RSA"
|
|
67
|
+
assert KeyringTypeEnum.KMS_KEY_CAPSULE.type == "key_capsule"
|
|
68
|
+
|
|
69
|
+
def test_get_raw_keyring_type(self):
|
|
70
|
+
result = KeyringTypeEnum.get_raw_keyring_type("AES")
|
|
71
|
+
assert result == KeyringTypeEnum.RAW_AES
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class TestErrorMessage:
|
|
75
|
+
def test_error_codes(self):
|
|
76
|
+
assert ErrorMessage.DECRYPT_EXCEPTION.code == 1000
|
|
77
|
+
assert ErrorMessage.CIPHER_EXCEPTION.code == 1001
|
|
78
|
+
assert ErrorMessage.KEYRING_NULL_EXCEPTION.code == 1012
|
|
79
|
+
assert ErrorMessage.KEY_CAPSULE_NULL.code == 1030
|
|
80
|
+
assert ErrorMessage.COLLECT_PROOF_EXCEPTION.code == 1036
|
|
81
|
+
|
|
82
|
+
def test_error_messages(self):
|
|
83
|
+
assert "decrypt" in ErrorMessage.DECRYPT_EXCEPTION.message.lower()
|
|
84
|
+
assert "null" in ErrorMessage.KEYRING_NULL_EXCEPTION.message.lower()
|
tests/test_exceptions.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from huaweicloud_encryptionsdk.exception.errors import (
|
|
3
|
+
HuaweicloudException,
|
|
4
|
+
KeyringNotFoundException,
|
|
5
|
+
KeyringNotMatchException,
|
|
6
|
+
KeyParseException,
|
|
7
|
+
EncryptException,
|
|
8
|
+
CipherTamperedException,
|
|
9
|
+
CipherDataException,
|
|
10
|
+
ErrorMessage,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class TestExceptions:
|
|
15
|
+
def test_huaweicloud_exception_message(self):
|
|
16
|
+
e = HuaweicloudException("test error")
|
|
17
|
+
assert str(e) == "test error"
|
|
18
|
+
|
|
19
|
+
def test_keyring_not_found_exception(self):
|
|
20
|
+
e = KeyringNotFoundException(ErrorMessage.KEYRING_NULL_EXCEPTION.message)
|
|
21
|
+
assert "key ring" in str(e).lower() or "null" in str(e).lower()
|
|
22
|
+
|
|
23
|
+
def test_cipher_tampered_exception(self):
|
|
24
|
+
e = CipherTamperedException(ErrorMessage.TAMPERED_EXCEPTION.message)
|
|
25
|
+
assert "integrity" in str(e).lower() or "tampered" in str(e).lower() or "Header" in str(e)
|
|
26
|
+
|
|
27
|
+
def test_exception_inheritance(self):
|
|
28
|
+
assert issubclass(KeyringNotFoundException, HuaweicloudException)
|
|
29
|
+
assert issubclass(KeyringNotMatchException, HuaweicloudException)
|
|
30
|
+
assert issubclass(KeyParseException, HuaweicloudException)
|
|
31
|
+
assert issubclass(EncryptException, HuaweicloudException)
|
|
32
|
+
assert issubclass(CipherTamperedException, HuaweicloudException)
|
|
33
|
+
assert issubclass(CipherDataException, HuaweicloudException)
|
|
34
|
+
|
|
35
|
+
def test_exception_with_cause(self):
|
|
36
|
+
cause = ValueError("original")
|
|
37
|
+
e = HuaweicloudException("wrapper", cause)
|
|
38
|
+
assert "wrapper" in str(e)
|