Рубрики
Без рубрики

Руководство по Google Think

Взгляните на криптографические API в библиотеке Tink, созданной инженерами Google

Автор оригинала: baeldung.

1. введение

В настоящее время многие разработчики используют криптографические методы для защиты пользовательских данных.

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

В этом уроке мы опишем Динь – многоязычная кросс-платформенная криптографическая библиотека, которая может помочь нам реализовать безопасный криптографический код.

2. Зависимости

Мы можем использовать Maven или Gradle для импорта мышления.

Для нашего урока мы просто добавим Зависимость Maven от Tink :


    com.google.crypto.tink
    tink
    1.2.2

Хотя вместо этого мы могли бы использовать Gradle:

dependencies {
  compile 'com.google.crypto.tink:tink:latest'
}

3. Инициализация

Перед использованием любого из API-интерфейсов Tink нам необходимо их инициализировать.

Если нам нужно использовать все реализации всех примитивов в Think, мы можем использовать метод Trunk Config.register() :

TinkConfig.register();

В то время как, например, если нам нужен только примитив AHEAD, мы можем использовать Опережающий Config.register() метод:

AeadConfig.register();

Для каждой реализации также предусмотрена настраиваемая инициализация.

4. Примитивы Динь-Динь

Основные объекты, используемые библиотекой, называются примитивами, которые, в зависимости от типа, содержат различные криптографические функции.

Примитив может иметь несколько реализаций:

Мы можем получить примитив, вызвав метод getPrimitive() соответствующего заводского класса, передав ему KeysetHandle :

Aead aead = AeadFactory.getPrimitive(keysetHandle);

4.1. keysethandletagsinformation

Чтобы обеспечить криптографическую функциональность, каждому примитиву нужна ключевая структура , содержащая все ключевые материалы и параметры.

Tink предоставляет объект – KeysetHandle– , который обертывает набор ключей с некоторыми дополнительными параметрами и метаданными.

Итак, перед созданием экземпляра примитива нам нужно создать дескриптор набора ключей объекта:

KeysetHandle keysetHandle = KeysetHandle.generateNew(AeadKeyTemplates.AES256_GCM);

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

String keysetFilename = "keyset.json";
CleartextKeysetHandle.write(keysetHandle, JsonKeysetWriter.withFile(new File(keysetFilename)));

Затем мы можем впоследствии загрузить его:

String keysetFilename = "keyset.json";
KeysetHandle keysetHandle = CleartextKeysetHandle.read(JsonKeysetReader.withFile(new File(keysetFilename)));

5. Шифрование

Think предоставляет несколько способов применения алгоритма AEAD. Давайте посмотрим.

5.1. ВПЕРЕДИ

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

Обратите внимание, что этот алгоритм обеспечивает подлинность и целостность связанных данных, но не их секретность.

Чтобы зашифровать данные с помощью одной из реализаций AEAD, как мы видели ранее, нам нужно инициализировать библиотеку и создать keysetHandle:

AeadConfig.register();
KeysetHandle keysetHandle = KeysetHandle.generateNew(
  AeadKeyTemplates.AES256_GCM);

Как только мы это сделаем, мы сможем получить примитив и зашифровать нужные данные:

String plaintext = "baeldung";
String associatedData = "Tink";

Aead aead = AeadFactory.getPrimitive(keysetHandle); 
byte[] ciphertext = aead.encrypt(plaintext.getBytes(), associatedData.getBytes());

Затем мы можем расшифровать зашифрованный текст с помощью метода decrypt() :

String decrypted = new String(aead.decrypt(ciphertext, associatedData.getBytes()));

5.2. Потоковая передача AEAD

Аналогично, когда данные, подлежащие шифрованию, слишком велики для обработки за один шаг, мы можем использовать примитив потоковой передачи ВПЕРЕД :

AeadConfig.register();
KeysetHandle keysetHandle = KeysetHandle.generateNew(
  StreamingAeadKeyTemplates.AES128_CTR_HMAC_SHA256_4KB);
StreamingAead streamingAead = StreamingAeadFactory.getPrimitive(keysetHandle);

FileChannel cipherTextDestination = new FileOutputStream("cipherTextFile").getChannel();
WritableByteChannel encryptingChannel =
  streamingAead.newEncryptingChannel(cipherTextDestination, associatedData.getBytes());

ByteBuffer buffer = ByteBuffer.allocate(CHUNK_SIZE);
InputStream in = new FileInputStream("plainTextFile");

while (in.available() > 0) {
    in.read(buffer.array());
    encryptingChannel.write(buffer);
}

encryptingChannel.close();
in.close();

В принципе, для этого нам нужен был Writablebytechannel .

Итак, чтобы расшифровать Зашифрованный файл, мы хотели бы использовать ReadableByteChannel :

FileChannel cipherTextSource = new FileInputStream("cipherTextFile").getChannel();
ReadableByteChannel decryptingChannel =
  streamingAead.newDecryptingChannel(cipherTextSource, associatedData.getBytes());

OutputStream out = new FileOutputStream("plainTextFile");
int cnt = 1;
do {
    buffer.clear();
    cnt = decryptingChannel.read(buffer);
    out.write(buffer.array());
} while (cnt>0);

decryptingChannel.close();
out.close();

6. Гибридное шифрование

В дополнение к симметричному шифрованию, Tink реализует несколько примитивов для гибридного шифрования.

С помощью гибридного шифрования мы можем получить эффективность симметричных ключей и удобство асимметричных ключей.

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

Обратите внимание, что он обеспечивает только секретность, а не подлинность личности отправителя.

Итак, давайте посмотрим, как использовать Гибридное шифрование и Гибридное дешифрование:

TinkConfig.register();

KeysetHandle privateKeysetHandle = KeysetHandle.generateNew(
  HybridKeyTemplates.ECIES_P256_HKDF_HMAC_SHA256_AES128_CTR_HMAC_SHA256);
KeysetHandle publicKeysetHandle = privateKeysetHandle.getPublicKeysetHandle();

String plaintext = "baeldung";
String contextInfo = "Tink";

HybridEncrypt hybridEncrypt = HybridEncryptFactory.getPrimitive(publicKeysetHandle);
HybridDecrypt hybridDecrypt = HybridDecryptFactory.getPrimitive(privateKeysetHandle);

byte[] ciphertext = hybridEncrypt.encrypt(plaintext.getBytes(), contextInfo.getBytes());
byte[] plaintextDecrypted = hybridDecrypt.decrypt(ciphertext, contextInfo.getBytes());

context Info – это неявные общедоступные данные из контекста, которые могут быть null или пустыми или использоваться в качестве входных данных “связанные данные” для шифрования AEAD или в качестве входных данных “CtxInfo” для HKDF.

зашифрованный текст позволяет проверить целостность контекстной информации , но не ее секретность или подлинность.

7. Код аутентификации Сообщения

Think также поддерживает коды аутентификации сообщений или MAC.

MAC-это блок из нескольких байтов, который мы можем использовать для аутентификации сообщения.

Давайте посмотрим, как мы можем создать MAC, а затем проверить его подлинность:

TinkConfig.register();

KeysetHandle keysetHandle = KeysetHandle.generateNew(
  MacKeyTemplates.HMAC_SHA256_128BITTAG);

String data = "baeldung";

Mac mac = MacFactory.getPrimitive(keysetHandle);

byte[] tag = mac.computeMac(data.getBytes());
mac.verifyMac(tag, data.getBytes());

В случае, если данные не являются подлинными, метод verify Mac() вызывает исключение GeneralSecurityException.

8. Цифровая подпись

Помимо API шифрования, Tink поддерживает цифровые подписи.

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

TinkConfig.register();

KeysetHandle privateKeysetHandle = KeysetHandle.generateNew(SignatureKeyTemplates.ECDSA_P256);
KeysetHandle publicKeysetHandle = privateKeysetHandle.getPublicKeysetHandle();

String data = "baeldung";

PublicKeySign signer = PublicKeySignFactory.getPrimitive(privateKeysetHandle);
PublicKeyVerify verifier = PublicKeyVerifyFactory.getPrimitive(publicKeysetHandle);

byte[] signature = signer.sign(data.getBytes()); 
verifier.verify(signature, data.getBytes());

Аналогично предыдущему методу шифрования, когда подпись недействительна, мы получим исключение GeneralSecurityException.

9. Заключение

В этой статье мы представили библиотеку Google Tink, используя ее реализацию на Java.

Мы видели, как использовать для шифрования и дешифрования данных, а также как защитить их целостность и подлинность. Кроме того, мы видели, как подписывать данные с помощью API цифровой подписи.

Как всегда, пример кода доступен на GitHub .