Skip to content

Commit aefdf4f

Browse files
committed
feat: support KMS 4.5.0
1 parent 7b04e78 commit aefdf4f

7 files changed

Lines changed: 79 additions & 61 deletions

File tree

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
test:
3232
services:
3333
kms:
34-
image: ghcr.io/cosmian/kms:4.4.3
34+
image: ghcr.io/cosmian/kms:4.5.0
3535
env:
3636
COSMIAN_SERVER_URL: http://localhost:9998
3737
KMS_PUBLIC_PATH: /tmp
@@ -94,7 +94,7 @@ jobs:
9494
extension: so
9595
destination: linux-x86-64
9696
os: ubuntu-20.04
97-
kms-version: 4.4.3
97+
kms-version: 4.5.0
9898
findex-cloud-version: 0.1.0
9999
copy_fresh_build: false
100100
copy_regression_files: |
@@ -107,7 +107,7 @@ jobs:
107107
with:
108108
branch: develop
109109
target: wasm32-unknown-unknown
110-
kms-version: 4.4.3
110+
kms-version: 4.5.0
111111
findex-cloud-version: 0.1.0
112112
copy_fresh_build: false
113113
copy_regression_files: |

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [4.1.0] - 2023-08-28
6+
7+
### Features
8+
9+
- Support KMS v4.5.0 with tagging support
10+
511
## [4.0.2] - 2023-07-17
612

713
### Miscellaneous Tasks

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ This table shows the minimum version correspondence between the various componen
9494

9595
| `cloudproof_py` | CoverCrypt | Findex | KMS |
9696
| --------------- | ---------- | ----------- | ----- |
97+
| >=4.1.0 | 11.0.0 | 4.0.0,4.0.1 | 4.5.0 |
9798
| >=4.0.2 | 11.0.0 | 4.0.0,4.0.1 | 4.4.3 |
9899
| >=4.0.1 | 11.0.0 | 4.0.0,4.0.1 | 4.4.2 |
99100
| >=4.0.0 | 11.0.0 | 4.0.0,4.0.1 | 4.3.3 |

examples/cover_crypt/main.py

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -50,23 +50,23 @@ async def main(use_kms: bool = True):
5050
# Messages encryption
5151
protected_mkg_data = b"protected_mkg_message"
5252
protected_mkg_ciphertext = await kms_client.cover_crypt_encryption(
53-
public_key_uid,
5453
"Department::MKG && Security Level::Protected",
5554
protected_mkg_data,
55+
public_key_uid,
5656
)
5757

58-
topSecret_mkg_data = b"top_secret_mkg_message"
59-
topSecret_mkg_ciphertext = await kms_client.cover_crypt_encryption(
60-
public_key_uid,
58+
top_secret_mkg_data = b"top_secret_mkg_message"
59+
top_secret_mkg_ciphertext = await kms_client.cover_crypt_encryption(
6160
"Department::MKG && Security Level::Top Secret",
62-
topSecret_mkg_data,
61+
top_secret_mkg_data,
62+
public_key_uid,
6363
)
6464

6565
protected_fin_data = b"protected_fin_message"
6666
protected_fin_ciphertext = await kms_client.cover_crypt_encryption(
67-
public_key_uid,
6867
"Department::FIN && Security Level::Protected",
6968
protected_fin_data,
69+
public_key_uid,
7070
)
7171

7272
# Generating user keys
@@ -86,15 +86,15 @@ async def main(use_kms: bool = True):
8686

8787
# Decryption with the right access policy
8888
protected_mkg_plaintext, _ = await kms_client.cover_crypt_decryption(
89-
confidential_mkg_user_uid, protected_mkg_ciphertext
89+
protected_mkg_ciphertext, confidential_mkg_user_uid
9090
)
9191
assert protected_mkg_plaintext == protected_mkg_data
9292

9393
# Decryption without the right access will fail
9494
try:
9595
# will throw
9696
await kms_client.cover_crypt_decryption(
97-
confidential_mkg_user_uid, topSecret_mkg_ciphertext
97+
top_secret_mkg_ciphertext, confidential_mkg_user_uid
9898
)
9999
except Exception as e:
100100
# ==> the user is not be able to decrypt
@@ -103,7 +103,7 @@ async def main(use_kms: bool = True):
103103
try:
104104
# will throw
105105
await kms_client.cover_crypt_decryption(
106-
confidential_mkg_user_uid, protected_fin_ciphertext
106+
protected_fin_ciphertext, confidential_mkg_user_uid
107107
)
108108
except Exception as e:
109109
# ==> the user is not be able to decrypt
@@ -113,17 +113,17 @@ async def main(use_kms: bool = True):
113113
# of all Security Level within the right Department
114114

115115
protected_mkg_plaintext2, _ = await kms_client.cover_crypt_decryption(
116-
topSecret_mkg_fin_user_uid, protected_mkg_ciphertext
116+
protected_mkg_ciphertext, topSecret_mkg_fin_user_uid
117117
)
118118
assert protected_mkg_plaintext2 == protected_mkg_data
119119

120120
topSecret_mkg_plaintext, _ = await kms_client.cover_crypt_decryption(
121-
topSecret_mkg_fin_user_uid, topSecret_mkg_ciphertext
121+
top_secret_mkg_ciphertext, topSecret_mkg_fin_user_uid
122122
)
123-
assert topSecret_mkg_plaintext == topSecret_mkg_data
123+
assert topSecret_mkg_plaintext == top_secret_mkg_data
124124

125125
protected_fin_plaintext, _ = await kms_client.cover_crypt_decryption(
126-
topSecret_mkg_fin_user_uid, protected_fin_ciphertext
126+
protected_fin_ciphertext, topSecret_mkg_fin_user_uid
127127
)
128128
assert protected_fin_plaintext == protected_fin_data
129129

@@ -132,29 +132,29 @@ async def main(use_kms: bool = True):
132132
# rotate MKG attribute
133133
# all active keys will be rekeyed automatically
134134
await kms_client.rotate_cover_crypt_attributes(
135-
private_key_uid, ["Department::MKG"]
135+
["Department::MKG"], private_key_uid
136136
)
137137

138138
# New confidential marketing message
139139

140140
confidential_mkg_data = b"confidential_secret_mkg_message"
141141
confidential_mkg_ciphertext = await kms_client.cover_crypt_encryption(
142-
public_key_uid,
143142
"Department::MKG && Security Level::Confidential",
144143
confidential_mkg_data,
144+
public_key_uid,
145145
)
146146

147147
# Decrypting the messages with the rekeyed key
148148

149149
# decrypting the "old" `protected marketing` message
150150
old_protected_mkg_plaintext, _ = await kms_client.cover_crypt_decryption(
151-
confidential_mkg_user_uid, protected_mkg_ciphertext
151+
protected_mkg_ciphertext, confidential_mkg_user_uid
152152
)
153153
assert old_protected_mkg_plaintext == protected_mkg_data
154154

155155
# decrypting the "new" `confidential marketing` message
156156
new_confidential_mkg_plaintext, _ = await kms_client.cover_crypt_decryption(
157-
confidential_mkg_user_uid, confidential_mkg_ciphertext
157+
confidential_mkg_ciphertext, confidential_mkg_user_uid
158158
)
159159
assert new_confidential_mkg_plaintext == confidential_mkg_data
160160

@@ -173,12 +173,12 @@ async def main(use_kms: bool = True):
173173
protected_mkg_data,
174174
)
175175

176-
topSecret_mkg_data = b"top_secret_mkg_message"
177-
topSecret_mkg_ciphertext = cover_crypt.encrypt(
176+
top_secret_mkg_data = b"top_secret_mkg_message"
177+
top_secret_mkg_ciphertext = cover_crypt.encrypt(
178178
policy,
179179
"Department::MKG && Security Level::Top Secret",
180180
public_key,
181-
topSecret_mkg_data,
181+
top_secret_mkg_data,
182182
)
183183

184184
protected_fin_data = b"protected_fin_message"
@@ -211,7 +211,7 @@ async def main(use_kms: bool = True):
211211
# Decryption without the right access will fail
212212
try:
213213
# will throw
214-
cover_crypt.decrypt(confidential_mkg_user_key, topSecret_mkg_ciphertext)
214+
cover_crypt.decrypt(confidential_mkg_user_key, top_secret_mkg_ciphertext)
215215
except Exception as e:
216216
# ==> the user is not be able to decrypt
217217
print("Expected error:", e)
@@ -232,9 +232,9 @@ async def main(use_kms: bool = True):
232232
assert protected_mkg_plaintext2 == protected_mkg_data
233233

234234
topSecret_mkg_plaintext, _ = cover_crypt.decrypt(
235-
topSecret_mkg_fin_user_key, topSecret_mkg_ciphertext
235+
topSecret_mkg_fin_user_key, top_secret_mkg_ciphertext
236236
)
237-
assert topSecret_mkg_plaintext == topSecret_mkg_data
237+
assert topSecret_mkg_plaintext == top_secret_mkg_data
238238

239239
protected_fin_plaintext, _ = cover_crypt.decrypt(
240240
topSecret_mkg_fin_user_key, protected_fin_ciphertext

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ cloudproof_py = ["py.typed", "*.pyi"]
77

88
[project]
99
name = "cloudproof_py"
10-
version = "4.0.2"
10+
version = "4.1.0"
1111
authors = [{ name = "Cosmian Tech", email = "tech@cosmian.com" }]
1212
description = "Python library for Cosmian Cloudproof"
1313
readme = "README.md"
@@ -20,7 +20,7 @@ dependencies = [
2020
"cloudproof-anonymization >= 0.1.0, < 1.0.0",
2121
"cover-crypt >= 11.0.0, < 12.0.0",
2222
"findex >= 4.0.0, < 5.0.0",
23-
"cosmian-kms >= 4.4.3, < 5.0.0",
23+
"cosmian-kms >= 4.5.0, < 5.0.0",
2424
"cloudproof-fpe >= 0.1.0, < 1.0.0",
2525
]
2626

src/cloudproof_py/kms/__init__.py

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,42 +29,49 @@ async def create_cover_crypt_master_key_pair(
2929
return await super().create_cover_crypt_master_key_pair(policy)
3030

3131
async def rotate_cover_crypt_attributes(
32-
self, master_secret_key_identifier: str, attributes: List[Union[Attribute, str]]
32+
self,
33+
attributes: List[Union[Attribute, str]],
34+
master_secret_key_identifier: Optional[str],
35+
tags: Optional[List[str]] = None,
3336
) -> Tuple[str, str]:
3437
"""Rotate the given policy attributes. This will rekey in the KMS:
3538
- the Master Keys
3639
- all User Decryption Keys that contain one of these attributes in their policy.
3740
3841
Args:
39-
master_secret_key_identifier (str): master secret key UID
4042
attributes (List[Union[Attribute, str]]): attributes to rotate e.g. ["Department::HR"]
43+
master_secret_key_identifier (str): master secret key UID
44+
tags: (Optional[List[str][]) tags to retrieve the master secret key if it the id is not satisfied
4145
4246
Returns:
4347
Tuple[str, str]: (Public key UID, Master secret key UID)
4448
"""
4549
return await super().rotate_cover_crypt_attributes(
46-
master_secret_key_identifier,
4750
[
4851
attr.to_string() if isinstance(attr, Attribute) else attr
4952
for attr in attributes
5053
],
54+
master_secret_key_identifier,
55+
tags,
5156
)
5257

5358
async def cover_crypt_encryption(
5459
self,
55-
public_key_identifier: str,
56-
access_policy_str: str,
60+
encryption_policy_str: str,
5761
data: bytes,
62+
public_key_identifier: Optional[str],
63+
tags: Optional[List[str]] = None,
5864
header_metadata: Optional[bytes] = None,
5965
authentication_data: Optional[bytes] = None,
6066
) -> bytes:
6167
"""Hybrid encryption. Concatenates the encrypted header and the symmetric
6268
ciphertext.
6369
6470
Args:
65-
public_key_identifier (str): identifier of the public key
66-
access_policy_str (str): the access policy to use for encryption
71+
encryption_policy_str (str): the access policy to use for encryption
6772
data (bytes): data to encrypt
73+
public_key_identifier (str): identifier of the public key
74+
tags: (Optional[List[str]]): tags to use to find the public key
6875
header_metadata (Optional[bytes]): additional data to encrypt in the header
6976
authentication_data (Optional[bytes]): authentication data to use in the encryption
7077
@@ -73,32 +80,35 @@ async def cover_crypt_encryption(
7380
"""
7481
return bytes(
7582
await super().cover_crypt_encryption(
76-
public_key_identifier,
77-
access_policy_str,
83+
encryption_policy_str,
7884
data,
85+
public_key_identifier,
86+
tags,
7987
header_metadata,
8088
authentication_data,
8189
)
8290
)
8391

8492
async def cover_crypt_decryption(
8593
self,
86-
user_key_identifier: str,
8794
encrypted_data: bytes,
95+
user_key_identifier: Optional[str],
96+
tags: Optional[List[str]] = None,
8897
authentication_data: Optional[bytes] = None,
8998
) -> Tuple[bytes, bytes]:
9099
"""Hybrid decryption.
91100
92101
Args:
93-
user_key_identifier (str): user secret key identifier
94102
encrypted_data (bytes): encrypted header || symmetric ciphertext
103+
user_key_identifier (str): user secret key identifier
104+
tags: (Optional[List[str]]): tags to use to find the user key
95105
authentication_data (Optional[bytes]): authentication data to use in the decryption
96106
97107
Returns:
98108
Future[Tuple[bytes, bytes]]: (plaintext bytes, header metadata bytes)
99109
"""
100110
plaintext, header = await super().cover_crypt_decryption(
101-
user_key_identifier, encrypted_data, authentication_data
111+
encrypted_data, user_key_identifier, tags, authentication_data
102112
)
103113
return bytes(plaintext), bytes(header)
104114

0 commit comments

Comments
 (0)