otdf-python 0.3.0__py3-none-any.whl → 0.3.5__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.
- otdf_python/asym_crypto.py +135 -22
- otdf_python/auth_headers.py +13 -1
- otdf_python/cli.py +20 -21
- otdf_python/ecc_constants.py +176 -0
- otdf_python/ecc_mode.py +60 -9
- otdf_python/ecdh.py +317 -0
- otdf_python/header.py +40 -2
- otdf_python/kas_client.py +172 -66
- otdf_python/kas_connect_rpc_client.py +7 -1
- otdf_python/nanotdf.py +445 -135
- otdf_python/policy_info.py +5 -28
- otdf_python/resource_locator.py +149 -21
- otdf_python/sdk.py +15 -107
- otdf_python/sdk_builder.py +5 -37
- otdf_python/tdf.py +4 -3
- {otdf_python-0.3.0.dist-info → otdf_python-0.3.5.dist-info}/METADATA +6 -84
- {otdf_python-0.3.0.dist-info → otdf_python-0.3.5.dist-info}/RECORD +19 -19
- otdf_python/asym_decryption.py +0 -53
- otdf_python/asym_encryption.py +0 -75
- {otdf_python-0.3.0.dist-info → otdf_python-0.3.5.dist-info}/WHEEL +0 -0
- {otdf_python-0.3.0.dist-info → otdf_python-0.3.5.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: otdf-python
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.5
|
|
4
4
|
Summary: Unofficial OpenTDF SDK for Python
|
|
5
5
|
Author-email: b-long <b-long@users.noreply.github.com>
|
|
6
6
|
License-File: LICENSE
|
|
@@ -32,65 +32,6 @@ Unofficial OpenTDF SDK for Python
|
|
|
32
32
|
|
|
33
33
|
A legacy version (0.2.x) of this project is available for users who need the previous implementation. For more information, see [LEGACY_VERSION.md](docs/LEGACY_VERSION.md) or visit the [legacy branch on GitHub](https://github.com/b-long/opentdf-python-sdk/tree/0.2.x).
|
|
34
34
|
|
|
35
|
-
## Prerequisites
|
|
36
|
-
|
|
37
|
-
This project uses [uv](https://docs.astral.sh/uv/) for dependency management and task running.
|
|
38
|
-
|
|
39
|
-
### Installing uv
|
|
40
|
-
|
|
41
|
-
Install `uv` using one of the following methods:
|
|
42
|
-
|
|
43
|
-
**macOS/Linux:**
|
|
44
|
-
```bash
|
|
45
|
-
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
**Windows:**
|
|
49
|
-
```powershell
|
|
50
|
-
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
**Using Homebrew (macOS):**
|
|
54
|
-
```bash
|
|
55
|
-
brew install uv
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
For more installation options, see the [uv installation guide](https://docs.astral.sh/uv/getting-started/installation/).
|
|
59
|
-
|
|
60
|
-
## Development Setup
|
|
61
|
-
|
|
62
|
-
1. Clone the repository:
|
|
63
|
-
```bash
|
|
64
|
-
git clone <repository-url>
|
|
65
|
-
cd opentdf-python-sdk
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
2. Install dependencies:
|
|
69
|
-
```bash
|
|
70
|
-
uv sync
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
## Running Tests
|
|
74
|
-
|
|
75
|
-
Run the full test suite:
|
|
76
|
-
```bash
|
|
77
|
-
uv run pytest tests/
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
Run specific test files:
|
|
81
|
-
```bash
|
|
82
|
-
uv run pytest tests/test_sdk.py
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
Run tests with verbose output:
|
|
86
|
-
```bash
|
|
87
|
-
uv run pytest tests/ -v
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
Run integration tests only:
|
|
91
|
-
```bash
|
|
92
|
-
uv run pytest tests/ -m integration
|
|
93
|
-
```
|
|
94
35
|
|
|
95
36
|
## Installation
|
|
96
37
|
|
|
@@ -99,21 +40,6 @@ Install from PyPI:
|
|
|
99
40
|
pip install otdf-python
|
|
100
41
|
```
|
|
101
42
|
|
|
102
|
-
|
|
103
|
-
## Protobuf & Connect RPC Generation
|
|
104
|
-
|
|
105
|
-
This project uses a dedicated submodule, `otdf-python-proto/`, for generating Python protobuf files and Connect RPC clients from OpenTDF platform proto definitions.
|
|
106
|
-
|
|
107
|
-
### Regenerating Protobuf & Connect RPC Files
|
|
108
|
-
|
|
109
|
-
From the submodule:
|
|
110
|
-
```bash
|
|
111
|
-
cd otdf-python-proto
|
|
112
|
-
uv run python scripts/generate_connect_proto.py
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
See [`otdf-python-proto/README.md`](otdf-python-proto/README.md) and [`PROTOBUF_SETUP.md`](PROTOBUF_SETUP.md) for details.
|
|
116
|
-
|
|
117
43
|
## Quick Start
|
|
118
44
|
|
|
119
45
|
### Basic Configuration
|
|
@@ -160,7 +86,7 @@ sdk = builder.build()
|
|
|
160
86
|
from io import BytesIO
|
|
161
87
|
|
|
162
88
|
# Create TDF configuration with attributes
|
|
163
|
-
config = sdk.new_tdf_config(attributes=["https://example.
|
|
89
|
+
config = sdk.new_tdf_config(attributes=["https://example.net/attr/attr1/value/value1"])
|
|
164
90
|
|
|
165
91
|
# Encrypt data to TDF format
|
|
166
92
|
input_data = b"Hello, World!"
|
|
@@ -176,23 +102,18 @@ with open("encrypted.tdf", "wb") as f:
|
|
|
176
102
|
### Decrypt Data
|
|
177
103
|
|
|
178
104
|
```python
|
|
179
|
-
from otdf_python.tdf import TDFReaderConfig
|
|
180
|
-
|
|
181
105
|
# Read encrypted TDF file
|
|
182
106
|
with open("encrypted.tdf", "rb") as f:
|
|
183
107
|
encrypted_data = f.read()
|
|
184
108
|
|
|
185
109
|
# Decrypt TDF
|
|
186
|
-
|
|
187
|
-
tdf_reader = sdk.load_tdf(encrypted_data, reader_config)
|
|
110
|
+
tdf_reader = sdk.load_tdf(encrypted_data)
|
|
188
111
|
decrypted_data = tdf_reader.payload
|
|
189
112
|
|
|
190
113
|
# Save decrypted data
|
|
191
114
|
with open("decrypted.txt", "wb") as f:
|
|
192
115
|
f.write(decrypted_data)
|
|
193
116
|
|
|
194
|
-
# Don't forget to close the SDK when done
|
|
195
|
-
sdk.close()
|
|
196
117
|
```
|
|
197
118
|
|
|
198
119
|
## Project Structure
|
|
@@ -208,6 +129,7 @@ src/otdf_python/
|
|
|
208
129
|
└── ... # Additional modules
|
|
209
130
|
tests/
|
|
210
131
|
└── ... # Various tests
|
|
132
|
+
```
|
|
211
133
|
|
|
212
134
|
## Contributing
|
|
213
135
|
|
|
@@ -215,14 +137,14 @@ tests/
|
|
|
215
137
|
2. Create a feature branch: `git checkout -b feature-name`
|
|
216
138
|
3. Make your changes
|
|
217
139
|
4. Run tests: `uv run pytest tests/`
|
|
218
|
-
5. Commit your changes: `git commit -am '
|
|
140
|
+
5. Commit your changes: `git commit -am 'feat: add feature'`
|
|
219
141
|
6. Push to the branch: `git push origin feature-name`
|
|
220
142
|
7. Submit a pull request
|
|
221
143
|
|
|
222
144
|
### Release Process
|
|
223
145
|
|
|
224
146
|
For maintainers and contributors working on releases:
|
|
225
|
-
- See [RELEASES.md](RELEASES.md) for comprehensive release documentation
|
|
147
|
+
- See [RELEASES.md](docs/RELEASES.md) for comprehensive release documentation
|
|
226
148
|
- Feature branch alpha releases available for testing changes before merge
|
|
227
149
|
- Automated releases via Release Please on the main branch
|
|
228
150
|
|
|
@@ -3,12 +3,10 @@ otdf_python/__main__.py,sha256=V9cmvhX9Ht2wpPOHGrw_onBogStJnuWTx9eyiezEDsQ,276
|
|
|
3
3
|
otdf_python/address_normalizer.py,sha256=pv7RoG4Dwac6so7NK1zCsVZBNFCcQK3cj_4iW6FPnRw,2815
|
|
4
4
|
otdf_python/aesgcm.py,sha256=KhMabIUYxxp1gUwdwNLiwD-SvmJPqW2PunbgeguMEh8,1666
|
|
5
5
|
otdf_python/assertion_config.py,sha256=P2Pc1OxMk9Ln6bvp1ZI8j66Q7uoZoYB7oMB6WLG38Y8,1763
|
|
6
|
-
otdf_python/asym_crypto.py,sha256=
|
|
7
|
-
otdf_python/
|
|
8
|
-
otdf_python/asym_encryption.py,sha256=ex-S_PvBnWKSSvbocTjJ_p5VQjjeiThcc9bMRZqvifw,2932
|
|
9
|
-
otdf_python/auth_headers.py,sha256=LFjfWiobNo9DNaPgcm-aJANzHZh7_u9oHTxnEzEq-Ro,562
|
|
6
|
+
otdf_python/asym_crypto.py,sha256=dwx3lUxUt3e8JA9z2lQrpsOBA3x36DN07bQbcVGZBvI,7251
|
|
7
|
+
otdf_python/auth_headers.py,sha256=a0TQD36QKXO1G4swume2wx3Sk9zQsSWEAQJnST2DlH0,966
|
|
10
8
|
otdf_python/autoconfigure_utils.py,sha256=NiNtbapBoIO-6kM59HRvX3Kj_Z0IRMrTkFlXjwuNfPc,3236
|
|
11
|
-
otdf_python/cli.py,sha256=
|
|
9
|
+
otdf_python/cli.py,sha256=0wXan-QrKQllIlSCnXDsFAT1EQpH7gv7g6TZKIVGI8E,19883
|
|
12
10
|
otdf_python/collection_store.py,sha256=MH1RxlevRVFj5lBS_6DN3zz5ZgOhBjD0P7AYBLBqS0o,1004
|
|
13
11
|
otdf_python/collection_store_impl.py,sha256=g3YeSwMeXr1BNmwmFr75fv9ptPjieC36Bhct-Jf1trw,613
|
|
14
12
|
otdf_python/config.py,sha256=uGYVByTWl7pWcKRER41ef-ay5VevIbOyUAEd6BIArVg,2185
|
|
@@ -16,30 +14,32 @@ otdf_python/connect_client.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
|
|
|
16
14
|
otdf_python/constants.py,sha256=SFGjrzB1GK4CkSZgNlEUIAZMY37MelTxgc8ajXIAhoc,53
|
|
17
15
|
otdf_python/crypto_utils.py,sha256=KsNss9EC-wHs1nCiKivDnxJSMv0uxGlWLDcCowadcV8,2837
|
|
18
16
|
otdf_python/dpop.py,sha256=ssKXTGydJS--rBTCqX9Y8qy-c5Um4pIZPG3DZcj0rWU,2301
|
|
19
|
-
otdf_python/
|
|
17
|
+
otdf_python/ecc_constants.py,sha256=uZkYeuhSnqCLjnrINOsaQQhdCKUTKLwL0t2Cswou4BA,5892
|
|
18
|
+
otdf_python/ecc_mode.py,sha256=8q-R_XR9WWmuzwI0gI6RQpsEzK8PD8Hi8uuDCvSsGXY,3077
|
|
19
|
+
otdf_python/ecdh.py,sha256=D8jHIZHYeQwCGCtjd3FJLXqIXnnYeEqSRLiWoiHZm1k,10233
|
|
20
20
|
otdf_python/eckeypair.py,sha256=4uZfdJaqSxW605FhU58Gko06mixSNoDOGBgVpP5VlSQ,2324
|
|
21
|
-
otdf_python/header.py,sha256=
|
|
21
|
+
otdf_python/header.py,sha256=0p259_GNO9aumUg0KOBZkiawKZTdFzoYVcyHaMCMVC8,7045
|
|
22
22
|
otdf_python/invalid_zip_exception.py,sha256=YEU20hM5_yE-RWJncPZobcqj4a90RAuahB54VjAS2SU,213
|
|
23
|
-
otdf_python/kas_client.py,sha256=
|
|
24
|
-
otdf_python/kas_connect_rpc_client.py,sha256=
|
|
23
|
+
otdf_python/kas_client.py,sha256=NP8T6G5SWuciJbYnX0QNrGGlpMhqTYbcjED2tfiTr8U,25938
|
|
24
|
+
otdf_python/kas_connect_rpc_client.py,sha256=LRhdFF6d8qz_BDFN4WMu0Kn-ZynvKMEWmuHYPj09A6Q,7862
|
|
25
25
|
otdf_python/kas_info.py,sha256=STnyPo-Vu_rzVQRdQl8mUGPK8eZE2vY4oPkI-PqrZJM,687
|
|
26
26
|
otdf_python/kas_key_cache.py,sha256=Ems2NyKC_3yh_xs8k4_n2gA3Jb-9nCeRRjIdz1LRC9I,1472
|
|
27
27
|
otdf_python/key_type.py,sha256=cwhlh6DOFG5C8JlCxFqXYi0SJDlOLUkxceg7L8arFNk,816
|
|
28
28
|
otdf_python/key_type_constants.py,sha256=ghridYdhFMLKDa_9Q5cplrl8DqdEgApd--20bJ-MBtA,1001
|
|
29
29
|
otdf_python/manifest.py,sha256=Uv-Hvo9hOPLrSPTeKQpDvNeHzq7qSmJ5HYtkgGwVppE,6419
|
|
30
|
-
otdf_python/nanotdf.py,sha256=
|
|
30
|
+
otdf_python/nanotdf.py,sha256=3pQ5Lip_pExhdfj2wqm58RS1Tb7A9f7dcxGIzVXSDuQ,33828
|
|
31
31
|
otdf_python/nanotdf_ecdsa_struct.py,sha256=nRScIJLeNcbxBBE9DlG15I7EXGTkH0ITib1ra-C1-uQ,4100
|
|
32
32
|
otdf_python/nanotdf_type.py,sha256=40PyDd62iDwcfmS7rhUeQE2B0W6FYIeCpi5cDmMO7d4,819
|
|
33
33
|
otdf_python/policy_binding_serializer.py,sha256=8d9MizhLTdy14ghdAvhXRBA8KzKt6Nf9kmmU9hoWhrQ,1169
|
|
34
|
-
otdf_python/policy_info.py,sha256=
|
|
34
|
+
otdf_python/policy_info.py,sha256=HGAOkxyB1I0N8_nHpnFkJXYJaycYsetqvWFNTxwwPi0,1951
|
|
35
35
|
otdf_python/policy_object.py,sha256=zzwHk6jhZwpiX2BWxTJ1kDl3cgFijQfQrKJP3OqI35Q,380
|
|
36
36
|
otdf_python/policy_stub.py,sha256=BQn06Ye5MwCu9feJZFPmO_UTfhugtiQa539iBkSQwhQ,117
|
|
37
|
-
otdf_python/resource_locator.py,sha256=
|
|
38
|
-
otdf_python/sdk.py,sha256=
|
|
39
|
-
otdf_python/sdk_builder.py,sha256=
|
|
37
|
+
otdf_python/resource_locator.py,sha256=vrTWtkIh82Ba4KRS6k6Pm92lQG5KazIQ18xX4VoX86Y,6050
|
|
38
|
+
otdf_python/sdk.py,sha256=7KKsjlUXL8_rUFVKoHFW37jvzS9Pi8Cww86NPyp3Kjw,14207
|
|
39
|
+
otdf_python/sdk_builder.py,sha256=jgswTxnAfKXDGqEOIQwEiE3S0Jh0w5HMtPxHwUFIu-U,14655
|
|
40
40
|
otdf_python/sdk_exceptions.py,sha256=L_bYkkyF-hnEBFXfjT5C41i5lM-t8OJB5mU_1zYvfP8,479
|
|
41
41
|
otdf_python/symmetric_and_payload_config.py,sha256=D_LArhk1gA5-tpUiaUZTTM90ZKdc3DCq1a6X8etCir8,992
|
|
42
|
-
otdf_python/tdf.py,sha256=
|
|
42
|
+
otdf_python/tdf.py,sha256=WYfCVn7BAEBKTVEPT0SSYuCI0S6S_TgYB3C3FbHProU,19612
|
|
43
43
|
otdf_python/tdf_reader.py,sha256=XQ3CuIXSOVRuBMYv2YIYlyaY-tHQA85HHHqNBoXNH9o,5267
|
|
44
44
|
otdf_python/tdf_writer.py,sha256=DVEGEl8pyBm1JK2K-9BJKmT2TqvQXokPkthAQMwgCkk,645
|
|
45
45
|
otdf_python/token_source.py,sha256=tfHWcIpPQ3FR45DUDiKz6q_vBaHH_HNifnnIpDVbMD8,923
|
|
@@ -131,7 +131,7 @@ otdf_python_proto/wellknownconfiguration/__init__.py,sha256=X3GeZJ1mG_N1MViryjkq
|
|
|
131
131
|
otdf_python_proto/wellknownconfiguration/wellknown_configuration_pb2.py,sha256=g9xSm9TxX0IPMqiFCaridJvI2TrL8PrXVFPgu8tX9VM,3863
|
|
132
132
|
otdf_python_proto/wellknownconfiguration/wellknown_configuration_pb2.pyi,sha256=Zw4vROvTgomnFqsalJrYda632ojXH0FVXSzTXxerybw,1490
|
|
133
133
|
otdf_python_proto/wellknownconfiguration/wellknown_configuration_pb2_connect.py,sha256=i9rGG2mgQZfk6xGCp1ywu4QqKWSiwpuLoNKGUwl43t8,5346
|
|
134
|
-
otdf_python-0.3.
|
|
135
|
-
otdf_python-0.3.
|
|
136
|
-
otdf_python-0.3.
|
|
137
|
-
otdf_python-0.3.
|
|
134
|
+
otdf_python-0.3.5.dist-info/METADATA,sha256=i1HQiMcbs71lXuIu0HCWxMo7EYlN130f95Mv0JulNsM,4225
|
|
135
|
+
otdf_python-0.3.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
136
|
+
otdf_python-0.3.5.dist-info/licenses/LICENSE,sha256=DPrPHdI6tfZcqk9kzQ37vh1Ftk7LJYdMrUtwKl7L3Pw,1074
|
|
137
|
+
otdf_python-0.3.5.dist-info/RECORD,,
|
otdf_python/asym_decryption.py
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import base64
|
|
2
|
-
|
|
3
|
-
from cryptography.hazmat.backends import default_backend
|
|
4
|
-
from cryptography.hazmat.primitives import hashes, serialization
|
|
5
|
-
from cryptography.hazmat.primitives.asymmetric import padding
|
|
6
|
-
|
|
7
|
-
from .sdk_exceptions import SDKException
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class AsymDecryption:
|
|
11
|
-
"""
|
|
12
|
-
Class providing functionality for asymmetric decryption using an RSA private key.
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
CIPHER_TRANSFORM = "RSA/ECB/OAEPWithSHA-1AndMGF1Padding"
|
|
16
|
-
PRIVATE_KEY_HEADER = "-----BEGIN PRIVATE KEY-----"
|
|
17
|
-
PRIVATE_KEY_FOOTER = "-----END PRIVATE KEY-----"
|
|
18
|
-
|
|
19
|
-
def __init__(self, private_key_pem: str | None = None, private_key_obj=None):
|
|
20
|
-
if private_key_obj is not None:
|
|
21
|
-
self.private_key = private_key_obj
|
|
22
|
-
elif private_key_pem is not None:
|
|
23
|
-
try:
|
|
24
|
-
private_key_pem = (
|
|
25
|
-
private_key_pem.replace(self.PRIVATE_KEY_HEADER, "")
|
|
26
|
-
.replace(self.PRIVATE_KEY_FOOTER, "")
|
|
27
|
-
.replace("\n", "")
|
|
28
|
-
.replace("\r", "")
|
|
29
|
-
.replace(" ", "")
|
|
30
|
-
)
|
|
31
|
-
decoded = base64.b64decode(private_key_pem)
|
|
32
|
-
self.private_key = serialization.load_der_private_key(
|
|
33
|
-
decoded, password=None, backend=default_backend()
|
|
34
|
-
)
|
|
35
|
-
except Exception as e:
|
|
36
|
-
raise SDKException(f"Failed to load private key: {e}")
|
|
37
|
-
else:
|
|
38
|
-
self.private_key = None
|
|
39
|
-
|
|
40
|
-
def decrypt(self, data: bytes) -> bytes:
|
|
41
|
-
if self.private_key is None:
|
|
42
|
-
raise SDKException("Failed to decrypt, private key is empty")
|
|
43
|
-
try:
|
|
44
|
-
return self.private_key.decrypt(
|
|
45
|
-
data,
|
|
46
|
-
padding.OAEP(
|
|
47
|
-
mgf=padding.MGF1(algorithm=hashes.SHA1()),
|
|
48
|
-
algorithm=hashes.SHA1(),
|
|
49
|
-
label=None,
|
|
50
|
-
),
|
|
51
|
-
)
|
|
52
|
-
except Exception as e:
|
|
53
|
-
raise SDKException(f"Error performing decryption: {e}")
|
otdf_python/asym_encryption.py
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import base64
|
|
2
|
-
import re
|
|
3
|
-
|
|
4
|
-
from cryptography.hazmat.backends import default_backend
|
|
5
|
-
from cryptography.hazmat.primitives import hashes, serialization
|
|
6
|
-
from cryptography.hazmat.primitives.asymmetric import padding
|
|
7
|
-
from cryptography.x509 import load_pem_x509_certificate
|
|
8
|
-
|
|
9
|
-
from .sdk_exceptions import SDKException
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class AsymEncryption:
|
|
13
|
-
"""
|
|
14
|
-
Provides methods for asymmetric encryption and handling public keys in PEM format.
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
PUBLIC_KEY_HEADER = "-----BEGIN PUBLIC KEY-----"
|
|
18
|
-
PUBLIC_KEY_FOOTER = "-----END PUBLIC KEY-----"
|
|
19
|
-
CIPHER_TRANSFORM = "RSA/ECB/OAEPWithSHA-1AndMGF1Padding"
|
|
20
|
-
|
|
21
|
-
def __init__(self, public_key_pem: str | None = None, public_key_obj=None):
|
|
22
|
-
if public_key_obj is not None:
|
|
23
|
-
self.public_key = public_key_obj
|
|
24
|
-
elif public_key_pem is not None:
|
|
25
|
-
try:
|
|
26
|
-
if "BEGIN CERTIFICATE" in public_key_pem:
|
|
27
|
-
cert = load_pem_x509_certificate(
|
|
28
|
-
public_key_pem.encode(), default_backend()
|
|
29
|
-
)
|
|
30
|
-
self.public_key = cert.public_key()
|
|
31
|
-
else:
|
|
32
|
-
# Remove PEM headers/footers and whitespace
|
|
33
|
-
pem_body = re.sub(r"-----BEGIN (.*)-----", "", public_key_pem)
|
|
34
|
-
pem_body = re.sub(r"-----END (.*)-----", "", pem_body)
|
|
35
|
-
pem_body = re.sub(r"\s", "", pem_body)
|
|
36
|
-
decoded = base64.b64decode(pem_body)
|
|
37
|
-
self.public_key = serialization.load_der_public_key(
|
|
38
|
-
decoded, backend=default_backend()
|
|
39
|
-
)
|
|
40
|
-
except Exception as e:
|
|
41
|
-
raise SDKException(f"Failed to load public key: {e}")
|
|
42
|
-
else:
|
|
43
|
-
self.public_key = None
|
|
44
|
-
|
|
45
|
-
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey
|
|
46
|
-
|
|
47
|
-
if self.public_key is not None and not isinstance(
|
|
48
|
-
self.public_key, RSAPublicKey
|
|
49
|
-
):
|
|
50
|
-
raise SDKException("Not an RSA PEM formatted public key")
|
|
51
|
-
|
|
52
|
-
def encrypt(self, data: bytes) -> bytes:
|
|
53
|
-
if self.public_key is None:
|
|
54
|
-
raise SDKException("Failed to encrypt, public key is empty")
|
|
55
|
-
try:
|
|
56
|
-
return self.public_key.encrypt(
|
|
57
|
-
data,
|
|
58
|
-
padding.OAEP(
|
|
59
|
-
mgf=padding.MGF1(algorithm=hashes.SHA1()),
|
|
60
|
-
algorithm=hashes.SHA1(),
|
|
61
|
-
label=None,
|
|
62
|
-
),
|
|
63
|
-
)
|
|
64
|
-
except Exception as e:
|
|
65
|
-
raise SDKException(f"Error performing encryption: {e}")
|
|
66
|
-
|
|
67
|
-
def public_key_in_pem_format(self) -> str:
|
|
68
|
-
try:
|
|
69
|
-
pem = self.public_key.public_bytes(
|
|
70
|
-
encoding=serialization.Encoding.PEM,
|
|
71
|
-
format=serialization.PublicFormat.SubjectPublicKeyInfo,
|
|
72
|
-
)
|
|
73
|
-
return pem.decode()
|
|
74
|
-
except Exception as e:
|
|
75
|
-
raise SDKException(f"Error exporting public key to PEM: {e}")
|
|
File without changes
|
|
File without changes
|