volcengine-python-sdk-aicc 0.0.41__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 (60) hide show
  1. bytedance/__init__.py +4 -0
  2. bytedance/jeddak_secure_channel/__init__.py +28 -0
  3. bytedance/jeddak_secure_channel/client.py +305 -0
  4. bytedance/jeddak_secure_channel/config.py +171 -0
  5. bytedance/jeddak_secure_channel/consts.py +5 -0
  6. bytedance/jeddak_secure_channel/crypto/__init__.py +14 -0
  7. bytedance/jeddak_secure_channel/crypto/aes.py +174 -0
  8. bytedance/jeddak_secure_channel/crypto/envelope.py +395 -0
  9. bytedance/jeddak_secure_channel/crypto/rsa.py +164 -0
  10. bytedance/jeddak_secure_channel/error.py +131 -0
  11. bytedance/jeddak_secure_channel/log/__init__.py +23 -0
  12. bytedance/jeddak_secure_channel/log/config.py +31 -0
  13. bytedance/jeddak_secure_channel/log/logger.py +88 -0
  14. bytedance/jeddak_secure_channel/logger_factory.py +134 -0
  15. bytedance/jeddak_secure_channel/ra.py +772 -0
  16. bytedance/jeddak_secure_channel/server.py +745 -0
  17. bytedance/jeddak_secure_channel/service/__init__.py +16 -0
  18. bytedance/jeddak_secure_channel/service/eps.py +133 -0
  19. bytedance/jeddak_secure_channel/service/eps_models.py +47 -0
  20. bytedance/jeddak_secure_channel/service/ras.py +88 -0
  21. bytedance/jeddak_secure_channel/service/tks.py +51 -0
  22. bytedance/jeddak_secure_channel/service/tks_models.py +334 -0
  23. bytedance/jeddak_secure_channel/utils.py +469 -0
  24. bytedance/jeddak_secure_model/model_automation_tool.py +181 -0
  25. bytedance/jeddak_secure_model/model_encryption.py +416 -0
  26. bytedance/jeddak_secure_model/model_hub_admin.py +116 -0
  27. bytedance/jeddak_secure_model/pcc_utils.py +279 -0
  28. bytedance/jeddak_secure_model/rds_utils.py +63 -0
  29. bytedance/tks/attester.py +41 -0
  30. bytedance/tks/client.py +629 -0
  31. bytedance/tks/consts.py +122 -0
  32. bytedance/tks/crypto/aes.py +47 -0
  33. bytedance/tks/crypto/ec.py +39 -0
  34. bytedance/tks/exceptions.py +22 -0
  35. bytedance/volcengine_aicc_sdk/__init__.py +14 -0
  36. bytedance/volcengine_aicc_sdk/aicc_client.py +277 -0
  37. bytedance/volcengine_aicc_sdk/aicc_inference.py +64 -0
  38. bytedance/volcengine_aicc_sdk/ark_inference_client.py +343 -0
  39. bytedance/volcengine_aicc_sdk/asr_inference_client.py +158 -0
  40. bytedance/volcengine_aicc_sdk/asr_websocket_client.py +705 -0
  41. bytedance/volcengine_aicc_sdk/auc_inference_client.py +305 -0
  42. bytedance/volcengine_aicc_sdk/common/__init__.py +0 -0
  43. bytedance/volcengine_aicc_sdk/common/aes.py +136 -0
  44. bytedance/volcengine_aicc_sdk/common/constant.py +4 -0
  45. bytedance/volcengine_aicc_sdk/common/error.py +21 -0
  46. bytedance/volcengine_aicc_sdk/common/log/__init__.py +24 -0
  47. bytedance/volcengine_aicc_sdk/common/log/config.py +31 -0
  48. bytedance/volcengine_aicc_sdk/common/log/logger.py +88 -0
  49. bytedance/volcengine_aicc_sdk/common/tos_utils.py +341 -0
  50. bytedance/volcengine_aicc_sdk/common/utils.py +45 -0
  51. bytedance/volcengine_aicc_sdk/cu_inference_client.py +292 -0
  52. bytedance/volcengine_aicc_sdk/deepseek_inference_client.py +501 -0
  53. bytedance/volcengine_aicc_sdk/secure_http_client.py +406 -0
  54. bytedance/volcengine_aicc_sdk/seedance_inference_client.py +500 -0
  55. bytedance/volcengine_aicc_sdk/seedream_inference_client.py +213 -0
  56. volcengine_python_sdk_aicc-0.0.41.dist-info/METADATA +79 -0
  57. volcengine_python_sdk_aicc-0.0.41.dist-info/RECORD +60 -0
  58. volcengine_python_sdk_aicc-0.0.41.dist-info/WHEEL +5 -0
  59. volcengine_python_sdk_aicc-0.0.41.dist-info/licenses/LICENSE +202 -0
  60. volcengine_python_sdk_aicc-0.0.41.dist-info/top_level.txt +1 -0
@@ -0,0 +1,629 @@
1
+ import base64
2
+ import dataclasses
3
+ import hashlib
4
+ import os
5
+ import secrets
6
+ from dataclasses import dataclass
7
+ from datetime import datetime, timedelta, timezone
8
+ import requests
9
+ from typing_extensions import IO, TYPE_CHECKING, Any, Dict, Optional, Union
10
+ from volcenginesdkcore.rest import ApiException
11
+ from bytedance.jeddak_secure_channel.ra import verify_ra_result, gen_report_data
12
+
13
+ from . import exceptions as exp
14
+ from .attester import EPSAttester
15
+ from .crypto import aes, ec
16
+
17
+ if TYPE_CHECKING:
18
+ from _typeshed import GenericPath
19
+ else:
20
+ GenericPath = str
21
+
22
+ __all__ = [
23
+ "TKSClient",
24
+ "TKSConfig",
25
+ ]
26
+
27
+ PATH_ATTEST = "/api/tks/v1/security/attest"
28
+ PATH_RING_CREATE = "/api/tks/v1/ring/create"
29
+ PATH_KEY_EXPORT = "/api/tks/v1/key/export"
30
+ PATH_KEY_CREATE = "/api/tks/v1/key/create"
31
+ PATH_KEY_IMPORT = "/api/tks/v1/key/import"
32
+ PATH_POLICY_SET = "/api/tks/v1/policy/set"
33
+ PATH_KEY_LIST = "/api/tks/v1/key/list"
34
+ PATH_RING_LIST = "/api/tks/v1/ring/list"
35
+ PATH_KEY_INFO = "/api/tks/v1/key/getinfo"
36
+ PATH_RAS_VERIFY = "/api/ras/v1/verify"
37
+
38
+
39
+ def utc8_timestamp() -> int:
40
+ return int(datetime.now(timezone(timedelta(hours=8))).timestamp())
41
+
42
+
43
+ @dataclass
44
+ class TKSConfig:
45
+ addr: str = "jeddakchain.bytedance.com"
46
+ pod_name: str = ""
47
+ enable_tls: bool = False
48
+ pcc_config: dict = dataclasses.field(default_factory=dict)
49
+ top_config: dict = dataclasses.field(default_factory=dict)
50
+
51
+
52
+ class TKSClient:
53
+ def __init__(self, app_id: str, config: TKSConfig) -> None:
54
+ self._app_id = app_id
55
+ self._config = config
56
+ self.attester = EPSAttester()
57
+ self.CHUNK_SIZE = 1024
58
+
59
+ def _request_tks(
60
+ self,
61
+ url: str,
62
+ body: Any,
63
+ headers: Optional[Dict[str, str]] = None,
64
+ cookies: Optional[Dict[str, str]] = None,
65
+ ) -> dict:
66
+ try:
67
+ if self._config.top_config:
68
+ if self._config.top_config.get("url_rewrite", ""):
69
+ from bytedance.jeddak_secure_channel.utils import (
70
+ request_bytedance_gateway,
71
+ )
72
+
73
+ resp = request_bytedance_gateway(
74
+ url, body, headers, self._config.top_config
75
+ )
76
+ else:
77
+ from bytedance.jeddak_secure_channel.utils import top_request
78
+
79
+ resp = top_request(url, body, headers, self._config.top_config)
80
+ else:
81
+ resp = requests.post(
82
+ url=url, json=body, headers=headers, cookies=cookies
83
+ )
84
+ except ApiException as e:
85
+ raise exp.TKSError(
86
+ "Status '{}' from TKS, URL: '{}', Content: {}".format(
87
+ e.status, url, e.body
88
+ ),
89
+ http_status=e.status
90
+ ) from e
91
+ except Exception as e:
92
+ raise exp.TKSError("Network error") from e
93
+ try:
94
+ if isinstance(resp, requests.Response):
95
+ resp.raise_for_status()
96
+ resp = resp.json()
97
+ except requests.HTTPError as e:
98
+ raise exp.TKSError(
99
+ "Status '{}' from TKS, URL: '{}', Content: {}".format(
100
+ resp.status_code, url, resp.text
101
+ ),
102
+ http_status=resp.status_code
103
+ ) from e
104
+ except requests.RequestException as e:
105
+ raise exp.TKSError("Bad connection to TKS: {}".format(e)) from e
106
+
107
+ # if "Result" not in resp:
108
+ # raise exp.TKSError("Unexpected response: {}".format(resp))
109
+ res = resp["Result"] if "Result" in resp else resp
110
+
111
+ return res
112
+
113
+ def challenge_server(self, nonce: str) -> str:
114
+ return self._do_server_ra(nonce)["Report"]
115
+
116
+ def create_ring(self, ring_name: str, desc: str = "", **kwargs) -> dict:
117
+ try:
118
+ if self._config.top_config:
119
+ url = self._config.addr
120
+ self._config.top_config["action"] = "CreateTksRing"
121
+ else:
122
+ url = self._get_tks_url(PATH_RING_CREATE)
123
+
124
+ result = self._request_tks(
125
+ url=url,
126
+ body={"RingName": ring_name, "Description": desc},
127
+ headers=self._get_headers(),
128
+ **kwargs,
129
+ )
130
+ return result
131
+ except requests.RequestException as e:
132
+ raise exp.TKSError("create_ring to TKS: {}".format(e)) from e
133
+
134
+ def create_key(
135
+ self,
136
+ ring_id: str,
137
+ algo: str,
138
+ key_name: str = "",
139
+ desc: str = "",
140
+ **kwargs,
141
+ ) -> dict:
142
+ key_meta = self._do_key_creation(
143
+ ring_id, algo=algo, key_name=key_name, src="internal", desc=desc, **kwargs
144
+ )
145
+ return key_meta
146
+
147
+ def import_key(
148
+ self,
149
+ ring_id: str,
150
+ algo: str,
151
+ key: bytes,
152
+ key_name: str = "",
153
+ desc: str = "",
154
+ usage_scenario="ModelEncryption",
155
+ **kwargs,
156
+ ) -> dict:
157
+ # Create an empty key record
158
+ key_meta = self._do_key_creation(
159
+ ring_id,
160
+ algo=algo,
161
+ key_name=key_name,
162
+ src="external",
163
+ desc=desc,
164
+ usage_scenario=usage_scenario,
165
+ **kwargs,
166
+ )
167
+
168
+ # Locally generate key pair
169
+ sk_local, pk_local = ec.generate_key_pair()
170
+
171
+ # Challenge server
172
+ ra_result = self._do_server_ra(bi_auth=False)
173
+ pk_server = base64.b64decode(ra_result["DHParam"].encode())
174
+
175
+ # Encrypt key
176
+ ek = ec.diffie_hellman_key_exchange(sk_local, pk_server)
177
+ encrypted_key = aes.gcm_encrypt(ek, key)
178
+
179
+ if self._config.top_config:
180
+ url = self._config.addr
181
+ self._config.top_config["action"] = "ImportTksKey"
182
+ else:
183
+ url = self._get_tks_url(PATH_KEY_IMPORT)
184
+
185
+ _ = self._request_tks(
186
+ url=url,
187
+ body={
188
+ "RingID": ring_id,
189
+ "KeyID": key_meta["KeyID"],
190
+ "Key": base64.b64encode(encrypted_key).decode(),
191
+ "DHParam": base64.b64encode(pk_local).decode(),
192
+ },
193
+ headers=self._get_headers(),
194
+ **kwargs,
195
+ )
196
+
197
+ return key_meta
198
+
199
+ def get_key_info(
200
+ self,
201
+ ring_id: str,
202
+ key_id: str,
203
+ ) -> dict:
204
+ if self._config.top_config:
205
+ url = self._config.addr
206
+ self._config.top_config["action"] = "GetTksKeyinfo"
207
+ else:
208
+ url = self._get_tks_url(PATH_KEY_INFO)
209
+ result = self._request_tks(
210
+ url=url,
211
+ body={
212
+ "RingID": ring_id,
213
+ "KeyID": key_id,
214
+ },
215
+ headers=self._get_headers(),
216
+ )
217
+
218
+ return result
219
+
220
+ def get_key(
221
+ self,
222
+ ring_id: str,
223
+ key_id: str,
224
+ need_evidence: bool = True,
225
+ attest_gpu: bool = True,
226
+ policy_id='',
227
+ tks_url='',
228
+ tks_uid='',
229
+ tks_service_name='',
230
+ **kwargs,
231
+ ) -> bytes:
232
+ print(f'tks get_key: policy_id={policy_id}, url={tks_url}, uid={tks_uid}, ra_service_name={tks_service_name}')
233
+ nonce = secrets.token_hex(32)
234
+ # 获取TKS的证明报告
235
+ ra_result = self._do_server_ra(nonce=nonce, bi_auth=True)
236
+ # 调用verify接口对TKS进行远程证明
237
+ if policy_id:
238
+ if self._config.top_config:
239
+ url = self._config.addr
240
+ self._config.top_config["action"] = "VerifyRasEvidence"
241
+ else:
242
+ url = self._get_tks_url(PATH_RAS_VERIFY)
243
+ report_data_bytes = gen_report_data(nonce, ra_result["Challenge"]["NonceDown"], ra_result["DHParam"],
244
+ ra_result['Challenge']['ExpirationTime'])
245
+
246
+ urlsafe_base64 = base64.urlsafe_b64encode(report_data_bytes)
247
+ report_data = urlsafe_base64.rstrip(b'=').decode('utf-8')
248
+ req_body = {
249
+ "Evidence": ra_result.get("Report").rstrip('='),
250
+ "PolicyId": policy_id,
251
+ "ReportData": {"Raw": report_data}
252
+ }
253
+ res = self._request_tks(
254
+ url=url, body=req_body, headers=self._get_headers(), **kwargs
255
+ )
256
+ verify_res = verify_ra_result(res.get("AttestationResult"), None, "", None, nonce,
257
+ report_data_bytes.hex())
258
+ if not verify_res:
259
+ raise Exception("verify tks failed!!!")
260
+ print("verify tks success!!!")
261
+
262
+ # get pub_key from server
263
+ pk_server = base64.b64decode(ra_result["DHParam"].encode())
264
+
265
+ sk_local, pk_local = ec.generate_key_pair()
266
+ req_body = {
267
+ "AppID": self._app_id,
268
+ "RingID": ring_id,
269
+ "KeyID": key_id,
270
+ "DHParam": base64.b64encode(pk_local).decode(),
271
+ "ClientChall": ra_result["Challenge"],
272
+ # "RAEvidence": {"TEEType": "coco", "Report": base64.b64encode(evidence).decode()},
273
+ }
274
+
275
+ if need_evidence:
276
+ evidence = self.attester.get_evidence(
277
+ ra_result["Challenge"]["NonceDown"][:64],
278
+ self._config.pod_name,
279
+ attest_gpu,
280
+ )
281
+
282
+ req_body["RAEvidence"] = {
283
+ "TEEType": "coco",
284
+ "Report": base64.b64encode(evidence).decode(),
285
+ }
286
+ if self._config.top_config:
287
+ url = self._config.addr
288
+ self._config.top_config["action"] = "ExportTksKey"
289
+ else:
290
+ url = self._get_tks_url(PATH_KEY_EXPORT)
291
+
292
+ res = self._request_tks(
293
+ url=url, body=req_body, headers=self._get_headers(), **kwargs
294
+ )
295
+
296
+ encrypted_key = res["Key"]
297
+
298
+ ek = ec.diffie_hellman_key_exchange(local_sk=sk_local, peer_pk=pk_server)
299
+
300
+ data_key = aes.gcm_decrypt(ek, base64.b64decode(encrypted_key))
301
+
302
+ return data_key
303
+
304
+ def set_key_policy(self, ring_id: str, key_id: str, policy: str, **kwargs) -> dict:
305
+ if self._config.top_config:
306
+ url = self._config.addr
307
+ self._config.top_config["action"] = "ImportTksKey"
308
+ else:
309
+ url = self._get_tks_url(PATH_POLICY_SET)
310
+
311
+ result = self._request_tks(
312
+ url=url,
313
+ headers=self._get_headers(),
314
+ body={
315
+ "ID": key_id,
316
+ "Range": "key",
317
+ "Rules": policy,
318
+ },
319
+ **kwargs,
320
+ )
321
+ return result
322
+
323
+ def _do_key_creation(
324
+ self,
325
+ ring_id: str,
326
+ algo: str,
327
+ key_name: str = "",
328
+ src: str = "internal",
329
+ desc: str = "",
330
+ usage_scenario: str = "ModelEncryption",
331
+ **kwargs,
332
+ ) -> dict:
333
+ if self._config.top_config:
334
+ url = self._config.addr
335
+ self._config.top_config["action"] = "CreateTksKey"
336
+ else:
337
+ url = self._get_tks_url(PATH_KEY_CREATE)
338
+ result = self._request_tks(
339
+ url=url,
340
+ body={
341
+ "RingID": ring_id,
342
+ "KeyName": key_name,
343
+ "Algo": algo,
344
+ "Source": src,
345
+ "Description": desc,
346
+ "UsageScenario": usage_scenario,
347
+ },
348
+ headers=self._get_headers(),
349
+ **kwargs,
350
+ )
351
+
352
+ return result
353
+
354
+ def list_ring_id(
355
+ self,
356
+ page_number: int = 0,
357
+ page_size: int = 10,
358
+ show_invisible: bool = False,
359
+ **kwargs,
360
+ ):
361
+ """
362
+ :param page_size:
363
+ :param page_number:
364
+ :param show_invisible:
365
+ :param kwargs:
366
+ :return:
367
+ """
368
+ try:
369
+ if self._config.top_config:
370
+ url = self._config.addr
371
+ self._config.top_config["action"] = "ListTksRing"
372
+ else:
373
+ url = self._get_tks_url(PATH_RING_LIST)
374
+
375
+ body = {
376
+ "PageSize": page_size,
377
+ "PageNumber": page_number,
378
+ "ShowInvisible": show_invisible,
379
+ }
380
+
381
+ result = self._request_tks(
382
+ url=url, body=body, headers=self._get_headers(), **kwargs
383
+ )
384
+ return result
385
+ except requests.RequestException as e:
386
+ raise exp.TKSError("list ring id error: {}".format(e)) from e
387
+
388
+ def list_key(
389
+ self,
390
+ ring_id: Optional[str] = None,
391
+ page_number: int = 0,
392
+ page_size: int = 10,
393
+ status: Optional[str] = None,
394
+ **kwargs,
395
+ ):
396
+ """
397
+ :param ring_id:
398
+ :param page_size:
399
+ :param page_number:
400
+ :param status:
401
+ :param kwargs:
402
+ :return:
403
+ """
404
+ try:
405
+ if self._config.top_config:
406
+ url = self._config.addr
407
+ self._config.top_config["action"] = "ListTksKey"
408
+ else:
409
+ url = self._get_tks_url(PATH_KEY_LIST)
410
+
411
+ body: dict = {"PageSize": page_size, "PageNumber": page_number}
412
+ if ring_id:
413
+ body["RingID"] = ring_id
414
+ if status:
415
+ body["Status"] = status
416
+
417
+ result = self._request_tks(
418
+ url=url, body=body, headers=self._get_headers(), **kwargs
419
+ )
420
+ return result
421
+ except requests.RequestException as e:
422
+ raise exp.TKSError("list key error: {}".format(e)) from e
423
+
424
+ def _do_server_ra(
425
+ self, nonce: Optional[str] = None, bi_auth: bool = True, **kwargs
426
+ ) -> dict:
427
+ if nonce is None:
428
+ nonce = secrets.token_hex(32)
429
+ if self._config.top_config:
430
+ url = self._config.addr
431
+ self._config.top_config["action"] = "AttestTksSecurity"
432
+ else:
433
+ url = self._get_tks_url(PATH_ATTEST)
434
+
435
+ resp = self._request_tks(
436
+ url=url,
437
+ body={"NonceUp": nonce, "BiAuth": bi_auth},
438
+ headers=self._get_headers(),
439
+ **kwargs,
440
+ )
441
+
442
+ return resp
443
+
444
+ def _get_tks_url(self, path: str) -> str:
445
+ if self._config.addr.startswith("http"):
446
+ return "{}{}".format(self._config.addr, path)
447
+ else:
448
+ scheme = "https" if self._config.enable_tls else "http"
449
+ return "{}://{}{}".format(scheme, self._config.addr, path)
450
+
451
+ def _generate_pcc_token(self, timestamp: str) -> str:
452
+ """
453
+ 生成访问bytedance pcc_controller的token
454
+ :param timestamp:
455
+ :return:
456
+ """
457
+ ak = self._config.pcc_config["ak"]
458
+ sk = self._config.pcc_config["sk"]
459
+
460
+ h = hashlib.sha256()
461
+ h.update(sk.encode())
462
+ sk = h.hexdigest()
463
+ h = hashlib.sha256()
464
+ h.update((ak + sk + str(timestamp)).encode())
465
+ token = h.hexdigest()
466
+ return token
467
+
468
+ def _get_headers(self) -> dict:
469
+ timestamp = str(int(datetime.now(timezone.utc).timestamp()))
470
+ headers = {
471
+ "AppID": self._app_id,
472
+ "X-Top-Account-Id": self._app_id,
473
+ # "Timestamp": str(utc8_timestamp()),
474
+ "Timestamp": timestamp,
475
+ # "nonce": "a314b43502077cd89d21378b29954207aaf5b3848d4d7fa9f16682ba1f6f3317"
476
+ }
477
+
478
+ if self._config.pcc_config:
479
+ headers["Content-Type"] = "application/json"
480
+ headers["J-Internal-Ak"] = self._config.pcc_config["ak"]
481
+ headers["J-Internal-Token"] = self._generate_pcc_token(timestamp)
482
+
483
+ return headers
484
+
485
+ def aes_encrypt(self, aes_key: Union[bytes, str], data: Union[bytes, str]) -> bytes:
486
+ if isinstance(aes_key, str):
487
+ aes_key = aes_key.encode()
488
+ if isinstance(data, str):
489
+ data = data.encode()
490
+ return aes.gcm_encrypt(aes_key, data)
491
+
492
+ def aes_decrypt(self, aes_key: Union[bytes, str], data: Union[bytes, str]) -> bytes:
493
+ if isinstance(aes_key, str):
494
+ aes_key = aes_key.encode()
495
+ if isinstance(data, str):
496
+ data = data.encode()
497
+ return aes.gcm_decrypt(aes_key, data)
498
+
499
+ def encrypt_file(
500
+ self,
501
+ aes_key: Union[bytes, str],
502
+ source_path: str,
503
+ dest_path: str,
504
+ mode: str = "b",
505
+ ) -> bool:
506
+ if mode not in ["b", "t"]:
507
+ raise Exception("mode argument error")
508
+
509
+ if isinstance(aes_key, str):
510
+ aes_key = aes_key.encode()
511
+
512
+ with open(source_path, f"r{mode}") as source, open(
513
+ dest_path, f"w{mode}"
514
+ ) as dest:
515
+ if mode == "b":
516
+ source_b: IO[bytes] = source
517
+ dest_b: IO[bytes] = dest
518
+ plaintext = source_b.read()
519
+ ciphertext = self.aes_encrypt(aes_key, plaintext)
520
+ dest_b.write(ciphertext)
521
+ else:
522
+ source_t: IO[str] = source
523
+ dest_t: IO[str] = dest
524
+ for plaintext in source_t:
525
+ plaintext = plaintext.rstrip("\n")
526
+ ciphertext = self.aes_encrypt(aes_key, plaintext)
527
+ dest_t.write(base64.b64encode(ciphertext).decode() + "\n")
528
+
529
+ return True
530
+
531
+ def decrypt_file(
532
+ self,
533
+ aes_key: Union[bytes, str],
534
+ source_path: str,
535
+ dest_path: str,
536
+ mode: str = "b",
537
+ ) -> bool:
538
+ if mode not in ["b", "t"]:
539
+ raise Exception("mode argument error")
540
+
541
+ if isinstance(aes_key, str):
542
+ aes_key = aes_key.encode()
543
+
544
+ with open(source_path, f"r{mode}") as source, open(
545
+ dest_path, f"w{mode}"
546
+ ) as dest:
547
+ if mode == "b":
548
+ source_b: IO[bytes] = source
549
+ dest_b: IO[bytes] = dest
550
+ ciphertext = source_b.read()
551
+ plaintext = self.aes_decrypt(aes_key, ciphertext)
552
+ dest_b.write(plaintext)
553
+ else:
554
+ source_t: IO[str] = source
555
+ dest_t: IO[str] = dest
556
+ for ciphertext in source_t:
557
+ ciphertext = ciphertext.rstrip("\n")
558
+ ciphertext = base64.b64decode(ciphertext.encode())
559
+ plaintext = self.aes_decrypt(aes_key, ciphertext)
560
+ dest_t.write(plaintext.decode() + "\n")
561
+ # dest_t.write(base64.b64encode(plaintext).decode() + "\n")
562
+ return True
563
+
564
+
565
+ default_config = TKSConfig()
566
+
567
+ if __name__ == "__main__":
568
+ def md5_hash(data: bytes, salt: str = "") -> str:
569
+ return hashlib.md5(data + salt.encode()).hexdigest()
570
+
571
+
572
+ ts = str(utc8_timestamp())
573
+ req_body = {"Username": "alice", "Password": md5_hash("alice0".encode(), ts)}
574
+ response = requests.post(
575
+ "https://jeddakchain.bytedance.com/api/user/login",
576
+ headers={"TimeStamp": ts},
577
+ json=req_body,
578
+ )
579
+ cookies = response.cookies
580
+ jeddak_pcc_session = cookies.get("jeddak_pcc_session")
581
+
582
+ cookies = {"jeddak_pcc_session": jeddak_pcc_session}
583
+
584
+ cfg = TKSConfig(addr="jeddakchain.bytedance.com", enable_tls=True)
585
+ client = TKSClient("alice", cfg)
586
+ # print(
587
+ # "Key Get",
588
+ # client.get_key(
589
+ # "2ee6348f-fafa-4e97-a824-0b6ed0e4d07e", "f532b84c-8f80-4705-b5a7-6217f4729924"
590
+ # ),
591
+ # )
592
+ #
593
+ # print("Challenge Server", client.challenge_server("1234"))
594
+ # print(
595
+ # "Key Creation",
596
+ # client.create_key(
597
+ # "4894a298-759a-4b94-a292-f43b2f8deea6",
598
+ # "SYMMETRIC_256",
599
+ # "test-encrypt-sdk",
600
+ # desc="测试本地加密SDK",
601
+ # cookies=cookies,
602
+ # ),
603
+ # )
604
+ # )
605
+ print(
606
+ "Key Insert",
607
+ client.import_key(
608
+ "4894a298-759a-4b94-a292-f43b2f8deea6",
609
+ "SYMMETRIC_256",
610
+ os.urandom(32),
611
+ "test-py-import",
612
+ cookies=cookies,
613
+ ),
614
+ )
615
+ # print("Key Set Policy", client.set_key_policy(
616
+ # "b3bf3cd7-2a68-427f-865f-8688dc96c7d8",
617
+ # "1110fb2f-8dca-4e27-9a37-04a60585fd29",
618
+ # json.dumps([
619
+ # [
620
+ # {
621
+ # "version": "v1",
622
+ # "type": "RAPolicy",
623
+ # "optional": False,
624
+ # "inversion": False,
625
+ # "policyID": "78485ba8-4e67-46a5-a34e-1a9b7930df02"
626
+ # }
627
+ # ]
628
+ # ])
629
+ # ))