|
14 | 14 |
|
15 | 15 | """Create / interact with Google Cloud Storage blobs.""" |
16 | 16 |
|
17 | | -import base64 |
| 17 | +from base64 import b64encode |
18 | 18 | import copy |
19 | 19 | import hashlib |
20 | 20 | from io import BytesIO |
|
28 | 28 | from six.moves.urllib.parse import quote |
29 | 29 |
|
30 | 30 | from gcloud._helpers import _rfc3339_to_datetime |
| 31 | +from gcloud._helpers import _to_bytes |
| 32 | +from gcloud._helpers import _from_bytes |
31 | 33 | from gcloud.credentials import generate_signed_url |
32 | 34 | from gcloud.exceptions import NotFound |
33 | 35 | from gcloud.exceptions import make_exception |
@@ -111,23 +113,6 @@ def path_helper(bucket_path, blob_name): |
111 | 113 | """ |
112 | 114 | return bucket_path + '/o/' + quote(blob_name, safe='') |
113 | 115 |
|
114 | | - @staticmethod |
115 | | - def _get_customer_encryption_headers(key): |
116 | | - """Builds customer encyrption key headers |
117 | | -
|
118 | | - :type key: str |
119 | | - :param key: 32 byte key to build request key and hash. |
120 | | - """ |
121 | | - headers = {} |
122 | | - key_hash = base64.encodestring(hashlib.sha256(key.encode('utf-8')) |
123 | | - .digest()).rstrip() |
124 | | - encoded_key = base64.encodestring(bytes(key.encode('utf-8'))).rstrip() |
125 | | - headers['X-Goog-Encryption-Algorithm'] = 'AES256' |
126 | | - headers['X-Goog-Encryption-Key'] = encoded_key.decode('utf-8') |
127 | | - headers['X-Goog-Encryption-Key-Sha256'] = key_hash.decode('utf-8') |
128 | | - |
129 | | - return headers |
130 | | - |
131 | 116 | @property |
132 | 117 | def acl(self): |
133 | 118 | """Create our ACL on demand.""" |
@@ -343,7 +328,7 @@ def download_to_file(self, file_obj, key=None, client=None): |
343 | 328 |
|
344 | 329 | headers = {} |
345 | 330 | if key: |
346 | | - headers.update(self._get_customer_encryption_headers(key)) |
| 331 | + set_customer_encryption_headers(key, headers) |
347 | 332 |
|
348 | 333 | request = Request(download_url, 'GET', headers) |
349 | 334 |
|
@@ -417,7 +402,7 @@ def _check_response_error(request, http_response): |
417 | 402 | raise make_exception(faux_response, http_response.content, |
418 | 403 | error_info=request.url) |
419 | 404 |
|
420 | | - # pylint: disable=too-many-arguments,too-many-locals |
| 405 | + # pylint: disable=too-many-locals |
421 | 406 | def upload_from_file(self, file_obj, rewind=False, size=None, key=None, |
422 | 407 | content_type=None, num_retries=6, client=None): |
423 | 408 | """Upload the contents of this blob from a file-like object. |
@@ -498,7 +483,7 @@ def upload_from_file(self, file_obj, rewind=False, size=None, key=None, |
498 | 483 | } |
499 | 484 |
|
500 | 485 | if key: |
501 | | - headers.update(self._get_customer_encryption_headers(key)) |
| 486 | + set_customer_encryption_headers(key, headers) |
502 | 487 |
|
503 | 488 | upload = Upload(file_obj, content_type, total_bytes, |
504 | 489 | auto_transfer=False) |
@@ -923,3 +908,21 @@ def __init__(self, bucket_name, object_name): |
923 | 908 | self.query_params = {'name': object_name} |
924 | 909 | self._bucket_name = bucket_name |
925 | 910 | self._relative_path = '' |
| 911 | + |
| 912 | + |
| 913 | +def set_customer_encryption_headers(key, headers): |
| 914 | + """Builds customer encyrption key headers |
| 915 | +
|
| 916 | + :type key: str |
| 917 | + :param key: 32 byte key to build request key and hash. |
| 918 | +
|
| 919 | + :type headers: dict |
| 920 | + :param headers: dict of HTTP headers being sent in request. |
| 921 | + """ |
| 922 | + key = _to_bytes(key) |
| 923 | + sha256_key = hashlib.sha256(key).digest() |
| 924 | + key_hash = b64encode(sha256_key).rstrip() |
| 925 | + encoded_key = b64encode(key).rstrip() |
| 926 | + headers['X-Goog-Encryption-Algorithm'] = 'AES256' |
| 927 | + headers['X-Goog-Encryption-Key'] = _from_bytes(encoded_key) |
| 928 | + headers['X-Goog-Encryption-Key-Sha256'] = _from_bytes(key_hash) |
0 commit comments