Проблема Google Cloud KMS с расшифровкой

Я новичок в Cloud KMS, и я начал точно следить за тем, что написано здесь

Я зашифровал свой файл данных, который сохранен в формате UTF-8, выполнив эту команду

gcloud kms encrypt --location global --keyring ring --key key --plaintext-file /path_to_file --ciphertext-file /path_to_enc --project myProject 

то в результате мои зашифрованные данные были представлены в этом формате в моем новом созданном зашифрованном файле

$�]ˋLݿ���yHI�lS�`&�Nt�b{%�U��   �&�A���XaL��d

вот как я читаю зашифрованные данные файла:

 static Properties properties = new Properties();

static {

    try {

        InputStream in = new Credentials().getClass().getResourceAsStream("path_to_enc_file");
        byte[] encryptedData = IOUtils.toByteArray(in);

        byte[] decryptedBytes = decrypt(EnvironmentVariable.getProjectId(), "global", "ring", "key", encryptedData);
        ByteArrayInputStream bis = new ByteArrayInputStream(decryptedBytes);

        properties.load(bis);           
        in.close();
        bis.close();
    } catch (IOException e1) {
        e1.printStackTrace();
    }
}

и теперь всякий раз, когда я пытаюсь расшифровать его с помощью этой функции:

public static byte[] decrypt(
    String projectId, String locationId, String keyRingId, String cryptoKeyId, byte[] ciphertext)
    throws IOException {

  // Create the KeyManagementServiceClient using try-with-resources to manage client cleanup.
  try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {

    // The resource name of the cryptoKey
    String resourceName = CryptoKeyName.format(projectId, locationId, keyRingId, cryptoKeyId);

    // Decrypt the ciphertext with Cloud KMS.
    DecryptResponse response = client.decrypt(resourceName, ByteString.copyFrom(ciphertext));

    // Extract the plaintext from the response.
    return response.getPlaintext().toByteArray();
  }
}

это бросить это

{
  "code" : 400,
  "errors" : [ {
    "domain" : "global",
    "message" : "Decryption failed: the ciphertext is invalid.",
    "reason" : "badRequest"
  } ],
  "message" : "Decryption failed: the ciphertext is invalid.",
  "status" : "INVALID_ARGUMENT"
}

тип ключа: Symmetric encrypt/decrypt Алгоритм по умолчанию: Google symmetric key

место на кольце: global

Не могли бы вы помочь мне и сказать, чего не хватает в документации Google?


person Tamer Saleh    schedule 10.03.2019    source источник
comment
Можете ли вы показать код, в котором вы читаете зашифрованный текст из файла? Мое чутье говорит, что есть проблема с кодировкой.   -  person hjfreyer    schedule 10.03.2019
comment
Я добавил это в вопрос   -  person Tamer Saleh    schedule 10.03.2019
comment
Хм, зашифрованный текст, который у вас есть в середине, действительно выглядит поврежденным (хотя, возможно, просто из-за копирования в SO). Делаете ли вы что-нибудь с файлом между командой gcloud и кодом Java, в котором вы его читаете? Мол, вы не копируете его из одного файла в другой, не так ли? И какая ОС? Также я могу подтвердить, что повреждение реально, если вы дадите мне версию зашифрованного текста в формате base64.   -  person hjfreyer    schedule 10.03.2019
comment
На самом деле я понятия не имею об этом base64, я просто следил за тем, что точно говорится в документации Google, и нет ничего между шифрованием с помощью команды gcloud kms и его расшифровкой с использованием предоставленного кода, а файл, содержащий зашифрованные данные, находится в UTF8 кодирование   -  person Tamer Saleh    schedule 10.03.2019
comment
и ОС, которую я использовал для запуска этой команды шифрования, - это MAC OS   -  person Tamer Saleh    schedule 10.03.2019
comment
Я попытался расшифровать файл с помощью команды glcoud kms decrypt, и она успешно работает, и я получил свои текстовые данные без каких-либо ошибок, так почему это не удалось из-за кода?   -  person Tamer Saleh    schedule 10.03.2019
comment
Хм, я не эксперт по Java, но я все же думаю, что что-то в данных повреждается во время загрузки файла. Можете ли вы запустить cat path_to_enc_file | openssl base64 и запустить свою программу, распечатывая ciphertext перед расшифровкой, и поместить оба результата в github gist?   -  person hjfreyer    schedule 10.03.2019
comment
Давайте продолжим это обсуждение в чате.   -  person Tamer Saleh    schedule 10.03.2019


Ответы (3)


Обновление: как сказано в комментарии bdhess, это, вероятно, связано с тем, что Maven «полезен» и повреждает данные в процессе сборки. Чтобы узнать, как избежать это.

Приведенное ниже решение также работает, но менее прямолинейно.


Мы с Тамером немного поболтали и нашли обходной путь:

  • Кодируйте вывод из gcloud в base64 перед включением его в файл в src/main/resources.
  • Расшифруйте файл после его прочтения с помощью java.util.Base64.
  • Передайте декодированные байты в KMS API.

По какой-то причине байты были повреждены между созданием файла с помощью gcloud и чтением байтов с помощью getResourceAsStream(). Из приведенного выше кода я не вижу, где могло произойти повреждение, и кажется, что чтение двоичных ресурсов должно полностью поддерживаться. Но где-то в случае Тамера что-то ломается.

Я постараюсь воспроизвести его где-нибудь на этой неделе.

person hjfreyer    schedule 10.03.2019
comment
Предполагая, что это построено с помощью Maven, вероятным виновником является фильтрация ресурсов в maven-resources-plugin во время сборки, которая обрабатывает большинство вещей в src/main/resources как текст. В документации показано, как указать дополнительный расширение файла, чтобы двоичные данные, такие как зашифрованные тексты Cloud KMS, не были повреждены фильтрацией ресурсов. - person bdhess; 11.03.2019

Я внес эти изменения, и они сработали как шарм с большой помощью @hjfreyer

1- чтобы зашифровать секретный текст, я сделал это

  • запустите эту команду ->

    gcloud kms encrypt --location global --plaintext-file PATH_TO_SECRET_FILE --ciphertext-file PATH_TO_TMP_FILE --project myProject --key key --keyring ring

  • Кодировать результат base64 ->

    base64 PATH_TO_TMP_FILE> PATH_TO_FINAL_ENC_FILE

  • удалить новую строку из файла FINAL_ENC_FILE

2- чтобы сначала расшифровать данные, мне нужно декодировать base64, а затем передать его функции дешифрования KMS

InputStream in = new Credentials().getClass().getResourceAsStream("PATH_TO_FINAL_ENC_FILE");
            byte[] encryptedData = IOUtils.toByteArray(in);


            byte[] decryptedBytes = decrypt(EnvironmentVariable.getProjectId(), "global", "ring", "key", Base64.getDecoder().decode(encryptedData));
person Tamer Saleh    schedule 11.03.2019
comment
для меня это не работает. Я просто запускаю val in = new FileInputStream("ciphertext/in/base64") val encryptedData = IOUtils.toByteArray(in) Base64.getDecoder().decode(encryptedData), это дает ошибку java.lang.IllegalArgumentException: Illegal base64 character a - person Alistair McIntyre; 10.02.2021

Чтобы расшифровать секрет из файла в файл с открытым текстом:

cat secret.enc | gcloud kms decrypt \
  --location=global \
  --keyring=keyring \
  --key=key \
  --ciphertext-file=- \
  --plaintext-file=decrypted_secret.txt
person Nebulastic    schedule 16.06.2020