C # с Google Storage - подписанный URL с ключом шифрования клиента - PullRequest
0 голосов
/ 27 января 2019

Я загрузил файл в хранилище Google.Теперь я сгенерировал его подписанный URL (на основе этого решения )

private static Uri SignUrl(Stream jsonCertificateStream, string bucketName, string objectName, TimeSpan expireAfter, string[] scopes, HttpMethod verb)
{
    string url;
    var urlSigner = UrlSigner.FromServiceAccountData(jsonCertificateStream);
    url = urlSigner.Sign(
                bucketName,
                objectName,
                expireAfter,
                verb);

    return new Uri(url);
}

Я получил URI, который хорошо работает с моим браузером.До здесь - все работает хорошо.

Теперь я использую ключ шифрования клиента для шифрования загруженного файла.Итак, я удалил файл и загрузил его снова - теперь он зашифрован.

Проблема в том, что теперь метод SignUrl() больше не работает.

При тестировании результата метода SignUrl() с браузером - я получаю:

<Error>
    <Code>ResourceIsEncryptedWithCustomerEncryptionKey</Code>
    <Message>
        The resource is encrypted with a customer encryption key.
    </Message>
    <Details>
        The requested object is encrypted by a customer-supplied encryption key.
    </Details>
</Error>

Я думаю, это потому, что мой файл зашифрован другим ключом.

Как это сделать правильно?

1 Ответ

0 голосов
/ 04 февраля 2019

На основе Документация по предоставленным клиентом ключам шифрования , вам необходимо добавить следующие заголовки при использовании предоставленных клиентом ключей шифрования

+------------------------------+--------+------------------------------------------------------------------------------+
|         Header name          | Value  |                                 Description                                  |
+------------------------------+--------+------------------------------------------------------------------------------+
| x-goog-encryption-algorithm  | string | The encryption algorithm to use. You must use the value AES256.              |
| x-goog-encryption-key        | string | An RFC 4648 Base64-encoded string of your AES-256 encryption key.            |
| x-goog-encryption-key-sha256 | string | An RFC 4648 Base64-encoded string of the SHA256 hash of your encryption key. |
+------------------------------+--------+------------------------------------------------------------------------------+

также при использовании urlSigner вы должны передать x-goog-encryption-алгоритма

вот пример кода

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Google.Cloud.Storage.V1;
using System.IO;
using System.Net.Http;
using Google.Apis.Auth.OAuth2;

namespace stackoverflow54387198
{
    class Program
    {
        static void Main(string[] args)
        {

            // step 1 create customer encryption key
            var key = EncryptionKey.Generate().Base64Key;

            var encryptionKey = EncryptionKey.Create(Convert.FromBase64String(key));


            // step 2 get you service Acount cert for auth

            string serviceAcountCert = "stackoverflow54387198-xxxxxxxx.json";

            // step 3 get you service Acount cert for auth

            string bucketName = "stackoverflow_54387198_bucket";

            string localPath = "FileToUpload.txt";

            string objectName = null;


            // step 4 create a local text file to upload

            File.WriteAllText(localPath, "test");


            // step 5 Create Google Storage Client

            var storage = StorageClient.Create(
                GoogleCredential.FromJson(File.ReadAllText(serviceAcountCert)));


            // step 6 upload the file with the customer encryption key from step 1

            using (var f = File.OpenRead(localPath))

            {

                objectName = objectName ?? Path.GetFileName(localPath);

                storage.UploadObject(bucketName, objectName, null, f,

                    new UploadObjectOptions()

                    {

                        EncryptionKey = encryptionKey

                    });

                Console.WriteLine($"Uploaded {objectName}.");

            }


            // step 7 create a url


            // step 7.1 create add x-goog-encryption-algorithm hear 
            //to tell google you are using  customer encryption key

            var requestHeaders = new Dictionary<string, IEnumerable<string>>
            {
                {
                    "x-goog-encryption-algorithm", new [] { "AES256" }
                }
            };


            // step 7.2  set other parameters

            var expireAfter = TimeSpan.FromHours(30.0);

            var verb = HttpMethod.Get;


            // step 7.3  create a Url Signer

            var urlSigner = UrlSigner.FromServiceAccountPath(serviceAcountCert);


            // step 7.4  create a secure url
            var url = urlSigner.Sign(
                        bucketName,
                        objectName,
                        expireAfter,
                        verb,
                        requestHeaders);



            // step 8  use the Your Url


            // step 8.1 create HttpClient

            var client = new HttpClient();


            // step 8.1  add x-goog-encryption-algorithm header the same from step 7

            client.DefaultRequestHeaders.Add("x-goog-encryption-algorithm", "AES256");


            // step 8.2  add x-goog-encryption-key header with customer encryption key (Base64Hash)

            client.DefaultRequestHeaders.Add("x-goog-encryption-key", encryptionKey.Base64Key);


            // step 8.3  add x-goog-encryption-key header with customer encryption key (Base64Hash)

            client.DefaultRequestHeaders.Add("x-goog-encryption-key-sha256", encryptionKey.Base64Hash);

            // step 8.4  Download the file 
            Task.Run(async () =>
            {
                var response = await client.GetAsync(url);
                var contents = await response.Content.ReadAsStringAsync();
                // contents == "test"
                Console.WriteLine($"contents=>{contents}");

            }).GetAwaiter().GetResult();

            Console.ReadLine();

        }


    }
}

также вы можете использовать почтальон для включения заголовков

image

исх. 1

Extra

Привет, Мохамед, спасибо за исчерпывающий ответ. В соответствии с вашими ответ, я понимаю, что я не могу просто сделать публичный подписанный URL, который будет использоваться для загрузки файла. Я всегда должен добавить дополнительные заголовки (алгоритм x-goog-encryption-key, ключ x-goog-encryption-key, ...) в Чтобы получить файл? Невозможно включить эти данные в Поле URL как-нибудь?

Чтобы ответить на этот вопрос, я буду использовать текущие вопросы:

  • перейти к вопросу 3 для решения

Вопрос 1

Невозможно как-то включить эти данные в поле URL?

Ответ 1

  • Я не знаю

Зачем отвечать 1?

  • база на моем логика

  • API хранилища Google представляет собой программное обеспечение, написанное программистом Google

  • из документации они ожидают, что ключ шифрования будет в заголовке

  • Если вы вызовете API без ключа в заголовке, он вернет сообщение об ошибке

  • так что, возможно, есть недокументированный способ, но я не знаю

Вопрос 2

В чем разница между параметрами HTTP и использованием заголовков HTTP

Ответ 2

Вопрос 3:

Как взломать это?

Ответ 3

  • если вы используете этот URL на веб-странице см .: javascript - Как установить заголовок для запроса HTTP GET и инициировать загрузку файла? - переполнение стека

  • если вы используете этот URL в мобильном приложении : вы можете скачать файл, используя swift или java или язык вашего приложения

  • если вы используете этот URL в электронном письме : вы можете создать свой собственный REST API, используя asp.net MVC или API, которые принимают ключ шифрования в качестве параметра, а затем вы действуете как прокси между Google может и клиентом браузера

Вопрос 4:

Что такое хранилище Google Параметры шифрования данных

Ответ 4

Cloud Storage всегда шифрует ваши данные на сервере сторона , перед записью на диск без дополнительной оплаты. Кроме этого стандартное поведение, есть дополнительные способы шифрования ваших данных, когда с помощью облачного хранилища. Ниже приведена сводка параметров шифрования доступны для вас:

  • Шифрование на стороне сервера : шифрование, которое происходит после того, как Cloud Storage получает ваши данные, но до того, как данные записываются на диск и сохраняются.

    • Заказные ключи шифрования : Вы можете создавать и управлять своими собственными ключами шифрования на стороне сервера шифрование, которое действует как дополнительный уровень шифрования поверх стандартное шифрование облачного хранилища.
    • Управляемые клиентом ключи шифрования : Вы можете создавать и управлять своими ключами шифрования, используя Cloud Key Сервис управления, который действует как дополнительный уровень шифрования сверху стандартного шифрования облачного хранилища.
  • Шифрование на стороне клиента : шифрование, которое происходит перед отправкой данных в облачное хранилище. Такие данные поступает в облачное хранилище уже в зашифрованном виде, но также подвергается шифрование на стороне сервера.

Вопрос 5:

Лучше использовать Клиентские ключи шифрования ?

Ответ 5:

  • это зависит от вашего программного обеспечения, но

    Облачное хранилище всегда шифрует ваши данные на стороне сервера, прежде чем записывается на диск без дополнительной оплаты

  • ref: Параметры шифрования данных | Облачное хранилище | Google Cloud

  • Может быть, вам не нужно шифровать данные с помощью предоставленных клиентом ключей шифрования , потому что Google шифрует данные в покое по умолчанию, а также к концу день, если вы боитесь, что Google шпионит за вами (только мои предположения как самого перфекциониста ?), это не логично, потому что вы отправляете ключ шифрования на те серверы, когда запрашиваете файл

исх. 2:

...