下列範例說明如何建立包含單一鍵和 並以明文形式儲存在磁碟中
琴鍵
tinkey create-keyset \
--key-template AES128_GCM \
--out-format json \
--out aead_keyset.json
Java
package cleartextkeyset; import com.google.crypto.tink.Aead; import com.google.crypto.tink.CleartextKeysetHandle; import com.google.crypto.tink.JsonKeysetReader; import com.google.crypto.tink.JsonKeysetWriter; import com.google.crypto.tink.KeyTemplates; import com.google.crypto.tink.KeysetHandle; import com.google.crypto.tink.aead.AeadConfig; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.security.GeneralSecurityException; /** * A command-line utility for generating, storing and using cleartext AES128_GCM keysets. * * <h1>WARNING: It loads cleartext keys from disk - this is not recommended! * * <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); } File keyFile = new File(args[1]); // Initialise Tink: register all AEAD key types with the Tink runtime AeadConfig.register(); if (MODE_GENERATE.equals(mode)) { KeysetHandle handle = KeysetHandle.generateNew(KeyTemplates.get("AES128_GCM")); try (FileOutputStream outputStream = new FileOutputStream(keyFile)) { CleartextKeysetHandle.write(handle, JsonKeysetWriter.withOutputStream(outputStream)); } System.exit(0); } // Use the primitive to encrypt/decrypt files // Read the cleartext keyset KeysetHandle handle = null; try (FileInputStream inputStream = new FileInputStream(keyFile)) { handle = CleartextKeysetHandle.read(JsonKeysetReader.withInputStream(inputStream)); } catch (GeneralSecurityException | IOException ex) { System.err.println("Error reading key: " + ex); System.exit(1); } // Get the primitive Aead aead = null; try { aead = handle.getPrimitive(Aead.class); } catch (GeneralSecurityException ex) { System.err.println("Error creating primitive: %s " + ex); System.exit(1); } byte[] input = Files.readAllBytes(Paths.get(args[2])); File outputFile = new File(args[3]); if (MODE_ENCRYPT.equals(mode)) { byte[] ciphertext = aead.encrypt(input, EMPTY_ASSOCIATED_DATA); try (FileOutputStream stream = new FileOutputStream(outputFile)) { stream.write(ciphertext); } } else if (MODE_DECRYPT.equals(mode)) { byte[] plaintext = aead.decrypt(input, EMPTY_ASSOCIATED_DATA); try (FileOutputStream stream = new FileOutputStream(outputFile)) { stream.write(plaintext); } } System.exit(0); } 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 cleartext_keyset_handle 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: cleartext_keyset_handle.write( tink.JsonKeysetWriter(keyset_file), keyset_handle) 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: 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 # 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)