Các ví dụ sau đây cho thấy cách tạo một keyset bằng một khoá duy nhất và lưu trữ khoá đó dưới dạng văn bản thuần tuý trên đĩa.
Tinkey
tinkey create-keyset \
--key-template AES128_GCM \
--out-format json \
--out aead_keyset.json
Java
package cleartextkeyset; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.crypto.tink.Aead; import com.google.crypto.tink.InsecureSecretKeyAccess; import com.google.crypto.tink.KeysetHandle; import com.google.crypto.tink.RegistryConfiguration; import com.google.crypto.tink.TinkJsonProtoKeysetFormat; import com.google.crypto.tink.aead.AeadConfig; import com.google.crypto.tink.aead.PredefinedAeadParameters; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; /** * A command-line utility for generating, storing and using AES128_GCM keysets. * * <h1>WARNING: Loading a Keyset from disk is often a security problem -- hence this needs {@code * InsecureSecretKeyAccess.get()}. * * <p>It requires the following arguments: * * <ul> * <li>mode: Can be "generate", "encrypt" or "decrypt". If mode is "generate" it will generate, * encrypt a keyset, store it in key-file. If mode is "encrypt" or "decrypt" it will read and * decrypt an keyset from key-file, and use it to encrypt or decrypt input-file. * <li>key-file: Read the encrypted key material from this file. * <li>input-file: If mode is "encrypt" or "decrypt", read the input from this file. * <li>output-file: If mode is "encrypt" or "decrypt", write the result to this file. */ public final class CleartextKeysetExample { private static final String MODE_ENCRYPT = "encrypt"; private static final String MODE_DECRYPT = "decrypt"; private static final String MODE_GENERATE = "generate"; private static final byte[] EMPTY_ASSOCIATED_DATA = new byte[0]; public static void main(String[] args) throws Exception { if (args.length != 2 && args.length != 4) { System.err.printf("Expected 2 or 4 parameters, got %d\n", args.length); System.err.println( "Usage: java CleartextKeysetExample generate/encrypt/decrypt key-file input-file" + " output-file"); System.exit(1); } String mode = args[0]; if (!MODE_ENCRYPT.equals(mode) && !MODE_DECRYPT.equals(mode) && !MODE_GENERATE.equals(mode)) { System.err.print("The first argument should be either encrypt, decrypt or generate"); System.exit(1); } Path keyFile = Paths.get(args[1]); // Initialise Tink: register all AEAD key types with the Tink runtime AeadConfig.register(); if (MODE_GENERATE.equals(mode)) { KeysetHandle handle = KeysetHandle.generateNew(PredefinedAeadParameters.AES128_GCM); String serializedKeyset = TinkJsonProtoKeysetFormat.serializeKeyset(handle, InsecureSecretKeyAccess.get()); Files.write(keyFile, serializedKeyset.getBytes(UTF_8)); return; } // Use the primitive to encrypt/decrypt files // Read the keyset from disk String serializedKeyset = new String(Files.readAllBytes(keyFile), UTF_8); KeysetHandle handle = TinkJsonProtoKeysetFormat.parseKeyset(serializedKeyset, InsecureSecretKeyAccess.get()); // Get the primitive Aead aead = handle.getPrimitive(RegistryConfiguration.get(), Aead.class); byte[] input = Files.readAllBytes(Paths.get(args[2])); Path outputFile = Paths.get(args[3]); if (MODE_ENCRYPT.equals(mode)) { byte[] ciphertext = aead.encrypt(input, EMPTY_ASSOCIATED_DATA); Files.write(outputFile, ciphertext); } else if (MODE_DECRYPT.equals(mode)) { byte[] plaintext = aead.decrypt(input, EMPTY_ASSOCIATED_DATA); Files.write(outputFile, plaintext); } } private CleartextKeysetExample() {} }
Go
import ( "bytes" "fmt" "log" "github.com/tink-crypto/tink-go/v2/aead" "github.com/tink-crypto/tink-go/v2/insecurecleartextkeyset" "github.com/tink-crypto/tink-go/v2/keyset" ) func Example_cleartextKeysetInBinary() { // Generate a new keyset handle for the primitive we want to use. handle, err := keyset.NewHandle(aead.AES256GCMKeyTemplate()) if err != nil { log.Fatal(err) } // Serialize the keyset. buff := &bytes.Buffer{} err = insecurecleartextkeyset.Write(handle, keyset.NewBinaryWriter(buff)) if err != nil { log.Fatal(err) } serializedKeyset := buff.Bytes() // serializedKeyset can now be stored at a secure location. // WARNING: Storing the keyset in cleartext to disk is not recommended! // Parse the keyset. parsedHandle, err := insecurecleartextkeyset.Read( keyset.NewBinaryReader(bytes.NewBuffer(serializedKeyset))) if err != nil { log.Fatal(err) } // Get the primitive. primitive, err := aead.New(parsedHandle) if err != nil { log.Fatal(err) } // Use the primitive. plaintext := []byte("message") associatedData := []byte("example encryption") ciphertext, err := primitive.Encrypt(plaintext, associatedData) if err != nil { log.Fatal(err) } decrypted, err := primitive.Decrypt(ciphertext, associatedData) if err != nil { log.Fatal(err) } fmt.Println(string(decrypted)) // Output: message }
Python
"""A command-line utility for generating, storing and using cleartext AES128_GCM keysets. It loads cleartext keys from disk - this is not recommended! """ from absl import app from absl import flags from absl import logging import tink from tink import aead from tink import secret_key_access FLAGS = flags.FLAGS flags.DEFINE_enum('mode', None, ['generate', '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.') def main(argv): del argv # Unused. # Initialise Tink aead.register() if FLAGS.mode == 'generate': # Generate a new keyset try: key_template = aead.aead_key_templates.AES128_GCM keyset_handle = tink.new_keyset_handle(key_template) except tink.TinkError as e: logging.exception('Error creating primitive: %s', e) return 1 with open(FLAGS.keyset_path, 'wt') as keyset_file: try: serialized_keyset = tink.json_proto_keyset_format.serialize( keyset_handle, secret_key_access.TOKEN ) keyset_file.write(serialized_keyset) except tink.TinkError as e: logging.exception('Error writing key: %s', e) return 1 return 0 # Use the input keyset to encrypt/decrypt data # Read the keyset into a keyset_handle with open(FLAGS.keyset_path, 'rt') as keyset_file: try: serialized_keyset = keyset_file.read() keyset_handle = tink.json_proto_keyset_format.parse( serialized_keyset, secret_key_access.TOKEN ) except tink.TinkError as e: logging.exception('Error reading key: %s', e) return 1 # Get the primitive try: cipher = keyset_handle.primitive(aead.Aead) except tink.TinkError as e: logging.error('Error creating primitive: %s', e) return 1 with open(FLAGS.input_path, 'rb') as input_file: input_data = input_file.read() if FLAGS.mode == 'decrypt': output_data = cipher.decrypt(input_data, b'envelope_example') elif FLAGS.mode == 'encrypt': output_data = cipher.encrypt(input_data, b'envelope_example') else: logging.error( 'Error mode not supported. Please choose "encrypt" or "decrypt".') return 1 with open(FLAGS.output_path, 'wb') as output_file: output_file.write(output_data) if __name__ == '__main__': flags.mark_flags_as_required(['mode', 'keyset_path']) app.run(main)