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.
Files changed (174) hide show
  1. examples/file_encryption_example.py +57 -0
  2. examples/key_capsule_encryption_example.py +240 -0
  3. examples/kms_discovery_encryption_example.py +56 -0
  4. examples/local_aes_encryption_example.py +59 -0
  5. examples/test_rsa.py +42 -0
  6. examples/test_sm2.py +38 -0
  7. examples/test_sm4_cbc.py +37 -0
  8. examples/test_sm4_gcm.py +37 -0
  9. huaweicloud_encryption_sdk_python-1.2.1.dist-info/METADATA +18 -0
  10. huaweicloud_encryption_sdk_python-1.2.1.dist-info/RECORD +174 -0
  11. huaweicloud_encryption_sdk_python-1.2.1.dist-info/WHEEL +5 -0
  12. huaweicloud_encryption_sdk_python-1.2.1.dist-info/top_level.txt +3 -0
  13. huaweicloud_encryptionsdk/__init__.py +5 -0
  14. huaweicloud_encryptionsdk/_apig_sdk/__init__.py +1 -0
  15. huaweicloud_encryptionsdk/_apig_sdk/signer.py +278 -0
  16. huaweicloud_encryptionsdk/_apig_sdk/signer_v11.py +70 -0
  17. huaweicloud_encryptionsdk/_apig_sdk/sm3_hash.py +141 -0
  18. huaweicloud_encryptionsdk/_lts_sdk/auth/__init__.py +0 -0
  19. huaweicloud_encryptionsdk/_lts_sdk/auth/signer.py +174 -0
  20. huaweicloud_encryptionsdk/_lts_sdk/consumer/__init__.py +0 -0
  21. huaweicloud_encryptionsdk/_lts_sdk/consumer/client/__init__.py +0 -0
  22. huaweicloud_encryptionsdk/_lts_sdk/consumer/client/consumer_client_adapter.py +59 -0
  23. huaweicloud_encryptionsdk/_lts_sdk/consumer/client/http_client.py +211 -0
  24. huaweicloud_encryptionsdk/_lts_sdk/consumer/core/__init__.py +0 -0
  25. huaweicloud_encryptionsdk/_lts_sdk/consumer/core/client_consumer_worker.py +106 -0
  26. huaweicloud_encryptionsdk/_lts_sdk/consumer/core/consumer_heartbeat.py +73 -0
  27. huaweicloud_encryptionsdk/_lts_sdk/consumer/core/log_shard_consumer.py +179 -0
  28. huaweicloud_encryptionsdk/_lts_sdk/consumer/interface/__init__.py +0 -0
  29. huaweicloud_encryptionsdk/_lts_sdk/consumer/interface/consumer_check_point_tracker.py +120 -0
  30. huaweicloud_encryptionsdk/_lts_sdk/consumer/interface/consumer_processor.py +18 -0
  31. huaweicloud_encryptionsdk/_lts_sdk/consumer/interface/consumer_processor_factory.py +3 -0
  32. huaweicloud_encryptionsdk/_lts_sdk/consumer/model/__init__.py +0 -0
  33. huaweicloud_encryptionsdk/_lts_sdk/consumer/model/check_point.py +20 -0
  34. huaweicloud_encryptionsdk/_lts_sdk/consumer/model/consumer_config.py +27 -0
  35. huaweicloud_encryptionsdk/_lts_sdk/consumer/model/log_data.py +18 -0
  36. huaweicloud_encryptionsdk/_lts_sdk/consumer/model/task_result.py +40 -0
  37. huaweicloud_encryptionsdk/_lts_sdk/consumer/task/__init__.py +0 -0
  38. huaweicloud_encryptionsdk/_lts_sdk/consumer/task/consumer_fetch_task.py +53 -0
  39. huaweicloud_encryptionsdk/_lts_sdk/consumer/task/initial_task.py +55 -0
  40. huaweicloud_encryptionsdk/_lts_sdk/consumer/task/process_task.py +25 -0
  41. huaweicloud_encryptionsdk/_lts_sdk/consumer/task/shutdown_task.py +24 -0
  42. huaweicloud_encryptionsdk/_lts_sdk/consumer_main.py +88 -0
  43. huaweicloud_encryptionsdk/_lts_sdk/parallel_main.py +64 -0
  44. huaweicloud_encryptionsdk/_lts_sdk/producer/__init__.py +0 -0
  45. huaweicloud_encryptionsdk/_lts_sdk/producer/callback/__init__.py +0 -0
  46. huaweicloud_encryptionsdk/_lts_sdk/producer/callback/call_back.py +7 -0
  47. huaweicloud_encryptionsdk/_lts_sdk/producer/core/__init__.py +0 -0
  48. huaweicloud_encryptionsdk/_lts_sdk/producer/core/accumulator.py +135 -0
  49. huaweicloud_encryptionsdk/_lts_sdk/producer/core/io_thread_pool.py +107 -0
  50. huaweicloud_encryptionsdk/_lts_sdk/producer/core/io_worker.py +124 -0
  51. huaweicloud_encryptionsdk/_lts_sdk/producer/core/mover.py +69 -0
  52. huaweicloud_encryptionsdk/_lts_sdk/producer/core/producer.py +98 -0
  53. huaweicloud_encryptionsdk/_lts_sdk/producer/lts_http/__init__.py +0 -0
  54. huaweicloud_encryptionsdk/_lts_sdk/producer/lts_http/http_client.py +63 -0
  55. huaweicloud_encryptionsdk/_lts_sdk/producer/lts_http/simple_request.py +14 -0
  56. huaweicloud_encryptionsdk/_lts_sdk/producer/model/__init__.py +0 -0
  57. huaweicloud_encryptionsdk/_lts_sdk/producer/model/config.py +50 -0
  58. huaweicloud_encryptionsdk/_lts_sdk/producer/model/error.py +18 -0
  59. huaweicloud_encryptionsdk/_lts_sdk/producer/model/log.py +87 -0
  60. huaweicloud_encryptionsdk/_lts_sdk/producer/model/log_batch.py +154 -0
  61. huaweicloud_encryptionsdk/_lts_sdk/producer/model/lts_store.py +21 -0
  62. huaweicloud_encryptionsdk/_lts_sdk/producer/model/result.py +17 -0
  63. huaweicloud_encryptionsdk/_lts_sdk/producer/model/retry_queue.py +39 -0
  64. huaweicloud_encryptionsdk/_lts_sdk/serial_main.py +77 -0
  65. huaweicloud_encryptionsdk/_lts_sdk/utils/__init__.py +0 -0
  66. huaweicloud_encryptionsdk/_lts_sdk/utils/common.py +57 -0
  67. huaweicloud_encryptionsdk/_lts_sdk/utils/lts_threading.py +32 -0
  68. huaweicloud_encryptionsdk/cache/__init__.py +0 -0
  69. huaweicloud_encryptionsdk/cache/data_key_cache.py +79 -0
  70. huaweicloud_encryptionsdk/cache/local_data_key_cache.py +161 -0
  71. huaweicloud_encryptionsdk/common/__init__.py +0 -0
  72. huaweicloud_encryptionsdk/common/constants.py +15 -0
  73. huaweicloud_encryptionsdk/common/counting_output_stream.py +18 -0
  74. huaweicloud_encryptionsdk/common/crypto_factory.py +48 -0
  75. huaweicloud_encryptionsdk/common/ec_private_key_loader.py +43 -0
  76. huaweicloud_encryptionsdk/common/ecs_metadata_service.py +42 -0
  77. huaweicloud_encryptionsdk/common/file_path_for_example_constants.py +4 -0
  78. huaweicloud_encryptionsdk/common/utils.py +162 -0
  79. huaweicloud_encryptionsdk/exception/__init__.py +0 -0
  80. huaweicloud_encryptionsdk/exception/errors.py +109 -0
  81. huaweicloud_encryptionsdk/handler/__init__.py +0 -0
  82. huaweicloud_encryptionsdk/handler/cipher_handler.py +294 -0
  83. huaweicloud_encryptionsdk/handler/crypto_handler.py +24 -0
  84. huaweicloud_encryptionsdk/handler/default_crypto_handler.py +148 -0
  85. huaweicloud_encryptionsdk/handler/default_serialize_handler.py +45 -0
  86. huaweicloud_encryptionsdk/handler/file_decrypt_handler.py +101 -0
  87. huaweicloud_encryptionsdk/handler/file_encrypt_handler.py +30 -0
  88. huaweicloud_encryptionsdk/handler/serialize_handler.py +14 -0
  89. huaweicloud_encryptionsdk/huawei_config.py +49 -0
  90. huaweicloud_encryptionsdk/huawei_crypto.py +311 -0
  91. huaweicloud_encryptionsdk/keyrings/__init__.py +0 -0
  92. huaweicloud_encryptionsdk/keyrings/keyring.py +14 -0
  93. huaweicloud_encryptionsdk/keyrings/keyring_factory.py +10 -0
  94. huaweicloud_encryptionsdk/keyrings/kms_keyring_factory.py +21 -0
  95. huaweicloud_encryptionsdk/keyrings/kmskeyring/__init__.py +0 -0
  96. huaweicloud_encryptionsdk/keyrings/kmskeyring/kms_discovery_keyring.py +51 -0
  97. huaweicloud_encryptionsdk/keyrings/kmskeyring/kms_key_capsule_keyring.py +100 -0
  98. huaweicloud_encryptionsdk/keyrings/kmskeyring/kms_keyring.py +155 -0
  99. huaweicloud_encryptionsdk/keyrings/kmskeyring/kms_multi_region_keyring.py +8 -0
  100. huaweicloud_encryptionsdk/keyrings/raw_keyring_factory.py +27 -0
  101. huaweicloud_encryptionsdk/keyrings/rawkeyring/__init__.py +0 -0
  102. huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_aes_keyring.py +63 -0
  103. huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_keyring.py +112 -0
  104. huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_rsa_keyring.py +55 -0
  105. huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_sm2_keyring.py +75 -0
  106. huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_sm4_cbc_keyring.py +66 -0
  107. huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_sm4_keyring.py +70 -0
  108. huaweicloud_encryptionsdk/kms/__init__.py +0 -0
  109. huaweicloud_encryptionsdk/kms/create_key_capsule_request.py +35 -0
  110. huaweicloud_encryptionsdk/kms/create_key_capsule_response.py +19 -0
  111. huaweicloud_encryptionsdk/kms/decrypt_key_capsule_request.py +32 -0
  112. huaweicloud_encryptionsdk/kms/decrypt_key_capsule_response.py +19 -0
  113. huaweicloud_encryptionsdk/kms/kms_http_client.py +116 -0
  114. huaweicloud_encryptionsdk/log/__init__.py +0 -0
  115. huaweicloud_encryptionsdk/log/log_config.py +30 -0
  116. huaweicloud_encryptionsdk/log/log_file_backup.py +144 -0
  117. huaweicloud_encryptionsdk/log/log_metrics.py +132 -0
  118. huaweicloud_encryptionsdk/log/log_reporter_manager.py +163 -0
  119. huaweicloud_encryptionsdk/log/lts_sdk_producer.py +386 -0
  120. huaweicloud_encryptionsdk/log/lts_struct_log_builder.py +106 -0
  121. huaweicloud_encryptionsdk/meterialmanager/__init__.py +0 -0
  122. huaweicloud_encryptionsdk/meterialmanager/cache_crypto_meterial_manager.py +221 -0
  123. huaweicloud_encryptionsdk/meterialmanager/crypto_meterial_manager.py +19 -0
  124. huaweicloud_encryptionsdk/meterialmanager/data_key_generate.py +10 -0
  125. huaweicloud_encryptionsdk/meterialmanager/data_key_generate_factory.py +20 -0
  126. huaweicloud_encryptionsdk/meterialmanager/default_crypto_meterials_manager.py +71 -0
  127. huaweicloud_encryptionsdk/meterialmanager/key_capsule_data_key_generate.py +63 -0
  128. huaweicloud_encryptionsdk/meterialmanager/kms_data_key_generate.py +65 -0
  129. huaweicloud_encryptionsdk/meterialmanager/local_data_key_generate.py +13 -0
  130. huaweicloud_encryptionsdk/model/__init__.py +0 -0
  131. huaweicloud_encryptionsdk/model/access_point_config.py +9 -0
  132. huaweicloud_encryptionsdk/model/cipher_body.py +81 -0
  133. huaweicloud_encryptionsdk/model/cipher_header.py +405 -0
  134. huaweicloud_encryptionsdk/model/ciphertext_data_key.py +166 -0
  135. huaweicloud_encryptionsdk/model/crypto_result.py +11 -0
  136. huaweicloud_encryptionsdk/model/data_key_materials.py +17 -0
  137. huaweicloud_encryptionsdk/model/data_materials.py +11 -0
  138. huaweicloud_encryptionsdk/model/enums/__init__.py +0 -0
  139. huaweicloud_encryptionsdk/model/enums/access_point_type.py +28 -0
  140. huaweicloud_encryptionsdk/model/enums/crypto_algorithm.py +75 -0
  141. huaweicloud_encryptionsdk/model/enums/data_key_generate_type.py +20 -0
  142. huaweicloud_encryptionsdk/model/enums/key_provider_enum.py +19 -0
  143. huaweicloud_encryptionsdk/model/enums/keyring_type_enum.py +27 -0
  144. huaweicloud_encryptionsdk/model/key_capsule.py +10 -0
  145. huaweicloud_encryptionsdk/model/key_capsule_config.py +12 -0
  146. huaweicloud_encryptionsdk/model/kms_config.py +10 -0
  147. huaweicloud_encryptionsdk/model/request/__init__.py +0 -0
  148. huaweicloud_encryptionsdk/model/request/encrypt_request.py +10 -0
  149. huaweicloud_encryptionsdk/model/request/sign_request.py +2 -0
  150. huaweicloud_encryptionsdk/model/request/verify_request.py +2 -0
  151. huaweicloud_encryptionsdk/proof/__init__.py +0 -0
  152. huaweicloud_encryptionsdk/proof/attestation_document.py +36 -0
  153. huaweicloud_encryptionsdk/proof/collector/__init__.py +0 -0
  154. huaweicloud_encryptionsdk/proof/collector/cce_proof_collector.py +24 -0
  155. huaweicloud_encryptionsdk/proof/collector/ecs_proof_collector.py +11 -0
  156. huaweicloud_encryptionsdk/proof/collector/key_pair_proof_collector.py +55 -0
  157. huaweicloud_encryptionsdk/proof/collector/ma_proof_collector.py +51 -0
  158. huaweicloud_encryptionsdk/proof/private_key_decrypt_callback.py +7 -0
  159. huaweicloud_encryptionsdk/proof/proof_collector.py +11 -0
  160. huaweicloud_encryptionsdk/proof/proof_collector_factory.py +53 -0
  161. huaweicloud_encryptionsdk/proof/proof_info.py +10 -0
  162. huaweicloud_encryptionsdk/util/__init__.py +0 -0
  163. huaweicloud_encryptionsdk/util/common_utils.py +12 -0
  164. tests/__init__.py +0 -0
  165. tests/test_enums.py +84 -0
  166. tests/test_exceptions.py +38 -0
  167. tests/test_factories.py +71 -0
  168. tests/test_huawei_crypto.py +67 -0
  169. tests/test_imports.py +46 -0
  170. tests/test_kms_models.py +95 -0
  171. tests/test_log_file_backup.py +45 -0
  172. tests/test_lts_struct_log_builder.py +97 -0
  173. tests/test_models.py +142 -0
  174. 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,10 @@
1
+ from dataclasses import dataclass
2
+ from typing import Optional
3
+
4
+
5
+ @dataclass
6
+ class KeyCapsule:
7
+ key_id: Optional[str] = None
8
+ datakey_capsule: Optional[str] = None
9
+ access_point_type: int = 0
10
+ instance_id: Optional[str] = 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
@@ -0,0 +1,10 @@
1
+ from dataclasses import dataclass
2
+ from typing import Optional
3
+
4
+
5
+ @dataclass
6
+ class KMSConfig:
7
+ region: str = ""
8
+ key_id: str = ""
9
+ project_id: str = ""
10
+ end_point: Optional[str] = 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
@@ -0,0 +1,2 @@
1
+ class SignRequest:
2
+ pass
@@ -0,0 +1,2 @@
1
+ class VerifyRequest:
2
+ pass
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,7 @@
1
+ from typing import Protocol
2
+
3
+
4
+ class PrivateKeyDecryptCallback(Protocol):
5
+
6
+ def decrypt(self, encrypted_private_key: str) -> str:
7
+ ...
@@ -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()
@@ -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)