I want to exchange data

Public key encryption involves protecting data with two keys, one public and one private. This allows you to share encrypted data with anyone who has the public key, but any data they send back can only be decrypted with the private key. If you need to encrypt data with a public key because the sender cannot store any secrets, use the Hybrid Encryption primitive.

We recommend the ECIES_P256_COMPRESSED_HKDF_HMAC_SHA256_AES128_GCM key type for most hybrid encryption use cases. For all supported key types, see Supported Key Types.

The following examples get you started using the Hybrid Encryption primitive.

Python

examples/python/hybrid/hybrid.py
"""A command-line utility for encrypting a file using hybrid encryption.

It loads cleartext keys from disk - this is not recommended!
"""

from __future__ import absolute_import
from __future__ import division
# Placeholder for import for type annotations
from __future__ import print_function

# Special imports
from absl import app
from absl import flags
from absl import logging
import tink
from tink import cleartext_keyset_handle
from tink import hybrid


FLAGS = flags.FLAGS

flags.DEFINE_enum('mode', None, ['encrypt', 'decrypt'],
                  'The operation to perform.')
flags.DEFINE_string('keyset_path', None,
                    'Path to the keyset used for encryption.')
flags.DEFINE_string('input_path', None, 'Path to the input file.')
flags.DEFINE_string('output_path', None, 'Path to the output file.')
flags.DEFINE_string('context_info', None,
                    'Context info used for encryption.')


def main(argv):
  del argv  # Unused

  context_info = b'' if not FLAGS.context_info else bytes(
      FLAGS.context_info, 'utf-8')

  # Initialise Tink
  try:
    hybrid.register()
  except tink.TinkError as e:
    logging.exception('Error initialising Tink: %s', e)
    return 1

  # Read the keyset into a keyset_handle
  with open(FLAGS.keyset_path, 'rt') as keyset_file:
    try:
      text = keyset_file.read()
      keyset_handle = cleartext_keyset_handle.read(tink.JsonKeysetReader(text))
    except tink.TinkError as e:
      logging.exception('Error reading key: %s', e)
      return 1

  with open(FLAGS.input_path, 'rb') as input_file:
    data = input_file.read()

  if FLAGS.mode == 'encrypt':
    # Get the primitive
    try:
      primitive = keyset_handle.primitive(hybrid.HybridEncrypt)
    except tink.TinkError as e:
      logging.exception(
          'Error creating hybrid encrypt primitive from keyset: %s', e)
      return 1
    # Encrypt data
    with open(FLAGS.output_path, 'wb') as output_file:
      ciphertext = primitive.encrypt(data, context_info)
      output_file.write(ciphertext)

  if FLAGS.mode == 'decrypt':
    # Get the primitive
    try:
      primitive = keyset_handle.primitive(hybrid.HybridDecrypt)
    except tink.TinkError as e:
      logging.exception(
          'Error creating hybrid encrypt primitive from keyset: %s', e)
      return 1
    # Decrypt data
    with open(FLAGS.output_path, 'wb') as output_file:
      plaintext = primitive.decrypt(data, context_info)
      output_file.write(plaintext)


if __name__ == '__main__':
  flags.mark_flags_as_required(
      ['mode', 'keyset_path', 'input_path', 'output_path'])
  app.run(main)

Java

examples/java_src/hybrid/HybridExample.java
package hybrid;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.crypto.tink.CleartextKeysetHandle;
import com.google.crypto.tink.HybridDecrypt;
import com.google.crypto.tink.HybridEncrypt;
import com.google.crypto.tink.JsonKeysetReader;
import com.google.crypto.tink.KeysetHandle;
import com.google.crypto.tink.hybrid.HybridConfig;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.security.GeneralSecurityException;

/**
 * A command-line utility for digitally signing and verifying a file.
 *
 * <p>It loads cleartext keys from disk - this is not recommended!
 *
 * <p>It requires the following arguments:
 *
 * <ul>
 *   <li>mode: either 'encrypt' or 'decrypt'.
 *   <li>key-file: Read the key material from this file.
 *   <li>input-file: Read the input from this file.
 *   <li>output-file: Write the result to this file.
 *   <li>[optional] contex-info: Bind the encryption to this context info.
 */
public final class HybridExample {
  public static void main(String[] args) throws Exception {
    if (args.length != 4 && args.length != 5) {
      System.err.printf("Expected 4 or 5 parameters, got %d\n", args.length);
      System.err.println(
          "Usage: java HybridExample encrypt/decrypt key-file input-file output-file context-info");
      System.exit(1);
    }

    String mode = args[0];
    if (!mode.equals("encrypt") && !mode.equals("decrypt")) {
      System.err.println("Incorrect mode. Please select encrypt or decrypt.");
      System.exit(1);
    }
    File keyFile = new File(args[1]);
    File inputFile = new File(args[2]);
    byte[] input = Files.readAllBytes(inputFile.toPath());
    File outputFile = new File(args[3]);
    byte[] contextInfo = new byte[0];
    if (args.length == 5) {
      contextInfo = args[4].getBytes(UTF_8);
    }

    // Register all hybrid encryption key types with the Tink runtime.
    HybridConfig.register();

    // Read the keyset into a KeysetHandle.
    KeysetHandle handle = null;
    try {
      handle = CleartextKeysetHandle.read(JsonKeysetReader.withFile(keyFile));
    } catch (GeneralSecurityException | IOException ex) {
      System.err.println("Cannot read keyset, got error: " + ex);
      System.exit(1);
    }

    if (mode.equals("encrypt")) {
      // Get the primitive.
      HybridEncrypt encryptor = null;
      try {
        encryptor = handle.getPrimitive(HybridEncrypt.class);
      } catch (GeneralSecurityException ex) {
        System.err.println("Cannot create primitive, got error: " + ex);
        System.exit(1);
      }

      // Use the primitive to encrypt data.
      byte[] ciphertext = encryptor.encrypt(input, contextInfo);
      try (FileOutputStream stream = new FileOutputStream(outputFile)) {
        stream.write(ciphertext);
      }
      System.exit(0);
    }

    // Get the primitive.
    HybridDecrypt decryptor = null;
    try {
      decryptor = handle.getPrimitive(HybridDecrypt.class);
    } catch (GeneralSecurityException ex) {
      System.err.println("Cannot create primitive, got error: " + ex);
      System.exit(1);
    }

    // Use the primitive to decrypt data.
    byte[] plaintext = decryptor.decrypt(input, contextInfo);
    try (FileOutputStream stream = new FileOutputStream(outputFile)) {
      stream.write(plaintext);
    }
    System.exit(0);
  }

  private HybridExample() {}
}