diff --git a/CHANGELOG.md b/CHANGELOG.md index 33683196e..392a11e32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed +* Fix missing key ID for large file encrypted with SSE-C +* Fix concatenating error message when message is None + + ## [1.24.0] - 2023-08-31 ### Added diff --git a/b2sdk/raw_api.py b/b2sdk/raw_api.py index 5f2202f36..ee9cd6c98 100644 --- a/b2sdk/raw_api.py +++ b/b2sdk/raw_api.py @@ -758,6 +758,9 @@ def start_large_file( ) kwargs['serverSideEncryption'] = server_side_encryption.serialize_to_json_for_request() + if server_side_encryption.mode == EncryptionMode.SSE_C: + file_info = server_side_encryption.add_key_id_to_file_info(file_info) + if legal_hold is not None: kwargs['legalHold'] = legal_hold.to_server() diff --git a/b2sdk/session.py b/b2sdk/session.py index 09fc23e17..95bb790a0 100644 --- a/b2sdk/session.py +++ b/b2sdk/session.py @@ -508,9 +508,7 @@ def _add_app_key_info_to_unauthorized(self, unauthorized): key_messages.append('with no restrictions') # Make a new message - new_message = unauthorized.message - if new_message == '': - new_message = 'unauthorized' + new_message = unauthorized.message or 'unauthorized' new_message += ' for application key ' + ', '.join(key_messages) return Unauthorized(new_message, unauthorized.code) diff --git a/test/integration/test_upload.py b/test/integration/test_upload.py index 479047e49..3bd8621e4 100644 --- a/test/integration/test_upload.py +++ b/test/integration/test_upload.py @@ -11,8 +11,14 @@ import io +from b2sdk.b2http import B2Http +from b2sdk.encryption.setting import EncryptionKey, EncryptionSetting +from b2sdk.encryption.types import EncryptionAlgorithm, EncryptionMode +from b2sdk.v2 import B2RawHTTPApi + from .base import IntegrationTestBase from .fixtures import b2_auth_data # noqa +from .test_raw_api import authorize_raw_api class TestUnboundStreamUpload(IntegrationTestBase): @@ -38,3 +44,38 @@ def test_streamed_large_buffer_small_part_size(self): data = b'a large data content' * 512 * 1024 # 5mb, the smallest allowed part size self.assert_data_uploaded_via_stream(data, part_size=5 * 1024 * 1024) + + +class TestUploadLargeFile(IntegrationTestBase): + def test_ssec_key_id(self): + sse_c = EncryptionSetting( + mode=EncryptionMode.SSE_C, + algorithm=EncryptionAlgorithm.AES256, + key=EncryptionKey(secret=b'********************************', key_id='some-id'), + ) + + raw_api = B2RawHTTPApi(B2Http()) + + auth_dict = authorize_raw_api(raw_api) + account_auth_token = auth_dict['authorizationToken'] + api_url = auth_dict['apiUrl'] + bucket = self.create_bucket() + + large_info = raw_api.start_large_file( + api_url, + account_auth_token, + bucket.id_, + 'test_largefile_sse_c.txt', + 'text/plain', + None, + server_side_encryption=sse_c, + ) + + assert large_info['fileInfo'] == { + 'sse_c_key_id': sse_c.key.key_id, + } + assert large_info['serverSideEncryption'] == { + 'algorithm': 'AES256', + 'customerKeyMd5': 'SaaDheEjzuynJH8eW6AEpQ==', + 'mode': 'SSE-C', + }