From 9322ec16ba282e59da41a12d3eb9c4a0baee88e8 Mon Sep 17 00:00:00 2001 From: Bartosz Przydatek <przydatek@google.com> Date: Fri, 19 May 2017 21:24:59 +0000 Subject: [PATCH] Merge "Updating and extending documentation" ORIGINAL_AUTHOR=Bartosz Przydatek <przydatek@google.com> GitOrigin-RevId: 52a2cfa9d56b6fa31817b27f4db77928ec1fbf6d --- README.md | 361 +++++++++++++++++++++++++++------------------- doc/JAVA-HOWTO.md | 107 ++++++++++++++ 2 files changed, 321 insertions(+), 147 deletions(-) create mode 100644 doc/JAVA-HOWTO.md diff --git a/README.md b/README.md index 8ffd08122..7797dcb6a 100644 --- a/README.md +++ b/README.md @@ -1,98 +1,231 @@ # Tink -Tink is a small cryptographic library that provides a safe, simple, agile and -fast way to accomplish some common cryptographic tasks. It is written by a -group of cryptographers and security engineers at Google, but it is not an -official Google product. +Tink is a cryptographic library that provides a safe, simple, agile and fast way +to accomplish common cryptographic tasks. It is written by a group of +cryptographers and security engineers at Google, but it is **not an official +Google product**. In particular, is not meant as a replacement or successor +of [Keyczar](https://github.com/google/keyczar). ## Getting started -TODO - -## Why Tink? - -We wrote this section so that you have a better idea of what Tink provides and -why we designed it this way. We’ve had a lot of joys working on Tink, and we -want to share with you what we’ve learned. We hope that you’d enjoy using -Tink, as much as we’ve enjoyed working on it! - -### Features +Tink performs cryptographic tasks via so-called _primitives_, each of which is +defined via a corresponding interface that specifies the functionality of the +primitive. For example, _symmetric key encryption_ is offered via an +_AEAD-primitive_ (Authenticated Encryption with Associated Data), that supports +two operations: + + * `encrypt(plaintext, associated_data)`, which encrypts the given `plaintext` + (using `associated_data` as additional AEAD-input) and returns the resulting + ciphertext + * `decrypt(ciphertext, associated_data)`, which decrypts the given `ciphertext` + (using `associated_data` as additional AEAD-input) and returns the resulting + ciphertext + +Currently Tink already provides primitives for several common crryptographic +operations (like symmetric encryption, message authentication codes, digital +signatures, hybrid encryption), and additional primitives are in preparation. +Moreover, adding new primitives or adding custom implementations of existing +primitives is quite straightforward. + +The basic use of Tink proceeds in three steps: + +1. Load or generate the cryptographic key material. +2. Use the key material to get an instance of a primitive. +3. Use the primitive to acomplish the cryptographic task. + +To be more concrete, here is how these steps would look like to perform +symmetric encryption (AEAD) in a Java program: + +``` java + import com.google.cloud.crypto.tink.Aead; + import com.google.cloud.crypto.tink.aead.AeadFactory; + import com.google.cloud.crypto.tink.KeysetHandle; + // (...) + + // 1. Get the key material. + KeysetHandle keysetHandle = ...; + // 2. Get the primitive. + Aead aead = AeadFactory.getPrimitive(keysetHandle); + // 3. Use the primitive. + byte[] ciphertext = aead.encrypt(plaintext, aad); +``` -Tink provides a set of basic tools to perform common crypto tasks in a variety -of environments. +In Step #1 above one can get a keysetHandle to an existing keyset kept in a +storage system... -Currently Tink supports the 4 fundamental crypto operations including -authenticated encryption with associated data (AEAD), message authentication -code (MAC), digital signature (PublicKeySign and PublicKeyVerify), and hybrid -encryption (HybridEncrypt and HybridDecrypt). In the future we might add other -primitives such as deterministic encryption (e.g., SIV modes), pseudorandom -function (e.g., HMAC as a PRF), strong pseudorandom permutation (e.g., HEH). +`KeysetHandle keysetHandle = SomeKeyStorage.loadKeyset(keysetId);` -Tink also supports -[envelope](http://docs.aws.amazon.com/kms/latest/developerguide/workflow.html) -[encryption](https://cloud.google.com/kms/docs/data-encryption-keys) which is -getting popular with Cloud users. In this mode, Cloud users generate a data -encryption key (DEK) locally, encrypt data with DEK, send DEK to a KMS such as -AWS KMS or Google Cloud KMS to be encrypted, and stores encrypted DEK with -encrypted data; at a later point Cloud users can retrieve encrypted data and DEK, -use the KMS to decrypt DEK, and use decrypted DEK to decrypt the data. +... or generate a fresh key material using the factory with a template which defines +the properties of the key that should be generated: +`KeysetHandle keysetHandle = CleartextKeysetHandle.generateNew(keyTemplate);` -#### Primitives +For other primitives the flow is analogous, we just have to use a corresponding +factory. For example here is how to use Message Authentication Code (MAC) +primitive: -The following AEAD algorithms are supported: +``` java + import com.google.cloud.crypto.tink.Mac; + import com.google.cloud.crypto.tink.mac.MacFactory; + import com.google.cloud.crypto.tink.KeysetHandle; + // (...) -- AES-EAX -- AES-GCM -- AES-CTR-HMAC-AEAD -- CHACHA20-POLY1305 (planned) + // 1. Get the key material. + KeysetHandle keysetHandle = ...; + // 2. Get the primitive. + Mac mac = MacFactory.getPrimitive(keysetHandle); + // 3. Use the primitive. + byte[] macValue = mac.computeMac(data); +``` -The following MAC algorithms are supported: +Before a specific implementation of a primitive can be used the Tink library +must be the initialized so that it "knows" the desired implementations. This +intialization happens via _registration_ of the implementations. For +example if one would like to use the standard implementations of AEAD and MAC +primitives offered by Tink, the initialization would look as follows: -- HMAC-SHA2 +``` java + import com.google.cloud.crypto.tink.aead.AeadFactory; + import com.google.cloud.crypto.tink.mac.MacFactory; + // (...) -The following digital signature algorithms are supported: + // Register standard implementations of AEAD and MAC primitives. + AeadFactory.registerStandardKeyTypes(); + MacFactory.registerStandardKeyTypes(); +``` -- ECDSA over NIST curves -- EdDSA over Ed25519 (planned) +Now that you already know how to use Tink (it is really that simple!), you can +proceed with using it in your code. Alternatively, you can continue reading the +sections below to get more information about the library: its features, +security, structure, extensibility, and more. To get direct instructions on how +to acomplish certain tasks with Tink +see [Java HOW-TO](https://github.com/google/tink/blob/master/doc/JAVA-HOWTO.md). -The following hybrid encryption algorithms are supported: +## Tink overview -- ECIES with AEAD and HKDF, based on [Victor Shoup's ISO 18033-2 design] -(http://www.shoup.net/iso/). -- NaCl CryptoBox (planned) +**Basic Features** Tink provides a set of basic tools to perform common crypto +tasks in a variety of environments. The main operations are accessible via +so-called _primitives_, which represent the corresponding cryptographic tools. +Currently Tink supports the following cryptographic operations: -#### Key Management +- authenticated encryption with associated data (primitive: AEAD) +- message authentication codes (primitive: MAC), +- digital signatures (primitives: PublicKeySign and PublicKeyVerify) +- hybrid encryption (primitives: HybridEncrypt and HybridDecrypt). -Key management is one of the most important aspects in any cryptosystem, but -it is also the most overlooked. Tink provides out of box support for storing -and loading keys from key management systems, and deliberately makes it hard -to resort to dangerous practices such as hard-coding keys in source code. +In the future other primitives will be added, e.g. deterministic encryption +(e.g., SIV modes), pseudorandom function (e.g., HMAC as a PRF), strong +pseudorandom permutation (e.g., HEH). -Tink supports the following key management systems: +**Envelope Encryption** Tink supports +[envelope](http://docs.aws.amazon.com/kms/latest/developerguide/workflow.html) +[encryption](https://cloud.google.com/kms/docs/data-encryption-keys) (a.k.a. KMS +Envelope) which is getting popular with Cloud users. In this mode, Cloud users +generate a data encryption key (DEK) locally, encrypt data with DEK, send DEK to +a KMS such as AWS KMS or Google Cloud KMS to be encrypted, and stores encrypted +DEK with encrypted data; at a later point Cloud users can retrieve encrypted +data and DEK, use the KMS to decrypt DEK, and use decrypted DEK to decrypt the +data. + +**Key Management** In addition to cryptographic operations Tink provides also +support for key management featuers like key versioning, key rotation, storing +and loading keys from key management systems, and more. For example, if a +cryptographic scheme is found broken, one can switch to a new implementation of +the primitive by rotating the key without changing or recompiling code. + +Currently tink supports the following key management systems: - Google Cloud KMS - Amazon KMS - Android Keystore System (planned) - Apple iOS KeyChain (planned) -You can easily add support for in-house key management system, without having +One can easily add support for in-house key management system, without having to change anything in Tink. -#### Languages - -Tink for Java is field tested and ready for production. C++ is in active -development and support for Go, Python, Javascript is in planning. +**Composability, Extensibility, and Interoperability** The core of Tink is +relatively small, and most components are recombinant. They can be selected and +assembled in various combinations to satisfy specific user requirements about +code size or performance. For example, if you need only digital signatures, you +don't have to include authenticated encryption. -For each language there is a pure implementation in that language and a native -one for users that want better performance. - -#### Platforms - -Tink supports Android, Linux (Google Cloud Engine or Amazon EC2), Google App -Engine. iOS support is in active development. +It is easy to add new primitives, protocols or interfaces to Tink. +Without touching the core library, can easily add support for new +algorithms, new ciphertext formats, or new key management systems (e.g., +in-house Hardware Security Modules), etc. -### Security +Tink produces and consumes ciphertexts that are compatible with other libraries. +Except in a few cases, implementations of crypto primitives in Tink come from +existing libraries such as OpenSSL, BoringSSL, NaCl, Bouncy Castle, OpenJDK, +etc. Because Tink is not a rewrite of these underlying libraries, but is rather +a high-level abstraction of them, it supports ciphertext formats and algorithms +supported by these libraries. + +**Languages and Platforms** Tink for Java is field tested and ready for +production. C++ is in active development and support for Go, Python, Javascript +is in planning. Tink supports Android, Linux (Google Cloud Engine or Amazon +EC2), Google App Engine. iOS support is in active development. + + +### Primitives and Their Implementations + +_Primitives_ represent cryptographic operations offered by Tink, hence they form +the core of Tink API. A primitive is just an interface that specifies what +operations are offered by the primitive. A primitive can have multiple +implementations, and user chooses a desired implementation by using a key of +corresponding type (see the [next section](#key-keyset-and-keysethandle) for details). +Although the implementations of a given primitive can be totally independent of +each other, they all have to fulfill some baseline requirements, to assure that +the use of a particular primitive does provide sufficient protections and does +not introduce security risks (see [Security and Safety](#security-and-safety) below). + +The following table summarizes Java implementations of primitives that are +currently available or planned (the latter are listed in brackets). + +| Primitive | Implementations | +|--------------------|-----------------------------------------------------| +| AEAD | AES-EAX, AES-GCM, AES-CTR-HMAC, KMS Envelope | +| MAC | HMAC-SHA2 | +| Digital Signatures | ECDSA over NIST curves, (EdDSA over Ed25519) | +| Hybrid Encryption | ECIES with AEAD and HKDF, (NaCl CryptoBox) | + +Tink user accesses implementations of a primitive via a factory that corresponds +to the primitive: AEAD-primitives are accessed via `AeadFactory`, MAC-primitives +via `MacFactory`, etc. where each factory offers corresponding +`getPrimitive(...)` methods. + +### Key, Keyset, and KeysetHandle + +A particular implementation of a _primitive_ is identified by a cryptographic +**key** structure that contains all key material and parameters needed to +provide the functionality of the primitive. The key structure is a _protocol +buffer_, whose globally unique name (a.k.a. _type url_) is referred to as **key +type**, and is used as an identifier of the corresponding implementation of a +primitive. Any particular implementation comes in a form of a **KeyManager** +which “understands†the key type: the manager can instantiate the primitive +corresponding to a given key, or can generate new keys of the supported key +type. + +To take advantage of key rotation and other key management features, a Tink user +works usually not with single keys, but with **keysets**, which are just sets of +keys with some additional parameters and metadata. In particular, this extra +information in the keyset dermines which key is _primary_ (i.e. will be used to +create new cryptographic data like ciphertexts, or signatures), which keys are +_enabled_ (i.e. can be used to process existing cryptographic data, like decrypt +ciphertext or verify signatures), and which keys should not be used any more. +For more details about the structure of keys, keysets and related protocol buffers see +[tink.proto](https://github.com/google/tink/blob/master/proto/tink.proto). + +The keys in a keyset can belong to _different implementations/key types_, but must +all implement the _same primitive_. Any given keyset (and any given key) can be +used for one primitive only. Moreover, to protect from accidental leakage or +corruption, an Tink user doesn’t work _directly_ with keysets, but rather with +KeysetHandle objects, which form a wrapper around the keysets. Creation of +KeysetHandle objects can be restricted to specific factories (whose visibility can +be governed by a white list), to enable control over actual storage of the keys +and keysets, and so avoid accidental leakage of secret key material. + +## Security and Safety Tink reduces common crypto pitfalls with user-centered design, careful implementation and code reviews, and extensive testing. @@ -103,13 +236,10 @@ real-world cryptosystems. We are also maintainers of validating the correctness of crypto libraries, thus Tink has been continuously tested and should be safe against known crypto weaknesses. -### Safety - -Tink provides APIs that decrease the potential for abuse or misuse. - -In particular, implementations of a high level interface are foolproof in the -sense: We assume that the attacker has complete freedom in calling methods of -a high level interface; under this assumption the security is not compromised. +Tink provides APIs that decrease the potential for abuse or misuse. In +particular, implementations of a high level interface are foolproof in the +sense: We assume that the attacker has complete freedom in calling methods of a +high level interface; under this assumption the security is not compromised. For example if the underlying encryption mode requires nonces and is insecure if nonces are reused then the interface do not allow to pass nonces. We also @@ -118,82 +248,21 @@ if a cryptographic operation (e.g. decryption) failed. Tink's interfaces abstract away from the underlying implementation. Instances are usable without knowing the underlying class that implements it. It is also -possible to change the underlying implementation of an interface without -changes to the call of the interface. Interfaces have security guarantees that -must be satisfied by each primitive implementing the interface. +possible to change the underlying implementation of an interface without changes +to the call of the interface. Interfaces have security guarantees that must be +satisfied by each primitive implementing the interface. This may exclude some +encryption modes. Rather than adding them to existing interfaces and weakening +the guarantees of the interface it is possible to add new interfaces and +describe the security guarantees appropriately. A good practice is to use each key for one purpose only. The storage format of Tink keys contains information such that correct usage of the key can be checked at runtime. -### Simplicity - -Tink provides APIs that are simple and easy to use. - -You can accomplish common crypto operations such as data encryption, digital -signatures, etc. with only a few lines of code. For example, to encrypt a -piece of data using authenticated encryption you need only 3 lines of code: - -``` -// 1. Read a keyset from some storage system -KeysetHandle keysetHandle = ... - -// 2. Get an instance of the Aead primitive. -Aead aead = AeadFactory.getPrimitive(keysetHandle); - -// 3. Use the primitive. -byte[] ciphertext = aead.encrypt(plaintext, associatedData); -``` - -### Composability - -The core of Tink is less than 2000 lines of code. - -All other components are recombinant that can be selected and assembled in -various combinations to satisfy specific user requirements about code size or -performance. For example, if you need only digital signatures, you don't have -to include authenticated encryption. This design allowed us to satisfy an -early user that needed a hybrid encryption library that, after compiled and -optimized, must be smaller than 5KB. - -### Extensibility - -It is easy to add new primitives, protocols or interfaces to Tink. - -Without touching the core library, you can easily add support for new -algorithms, new ciphertext formats, or new key management systems (e.g., -in-house Hardware Security Modules), etc. - -Interfaces for primitives typically have strong security guarantees and -frequently restrict parameter choices. This may exclude some encryption modes. -Rather than adding them to existing interfaces and weakening the guarantees of -the interface it is possible to add new interfaces and describe the security -guarantees appropriately. - -### Agility - -Tink provides out of box support for key rotation, deprecation of obsolete -schemes and adaptation of new ones. Once a crypto primitive is found broken, -you can switch to a new primitive by rotating the key without changing or -recompiling code. The library is also very versatile. No part of it is hard to -replace. - -### Interoperability - -Tink produces and consumes ciphertexts that are compatible with other -libraries. - -Except in a few cases, implementations of crypto primitives in Tink come from -existing libraries such as OpenSSL, BoringSSL, NaCl, Bouncy Castle, OpenJDK, -etc. Because Tink is not a rewrite of these underlying libraries, but is -rather a high-level abstraction of them, it supports ciphertext formats and -algorithms supported by these libraries. - -### Readability - -Tink shows crypto properties (i.e., whether safe against chosen-ciphertext -attacks) right in the interfaces, allowing security auditors and automated -tools quickly discovering incorrect usages. +**Readability** Tink declares cryptographic properties (e.g., whether safe +against chosen-ciphertext attacks) through the _primitives_ (i.e., interfaces), +allowing security auditors and automated tools quickly discovering incorrect +usages. On an abstract level we think that it is not necessary to know whether the cryptosystem has been proposed by Rivest, Shamir and Adleman or by Victor @@ -203,11 +272,9 @@ authenticated is more important than knowing it uses AES. This is why we name our interfaces as generic as possible (e.g., Aead, PublicKeySign, etc.), but not too general (e.g., Crypter, Signer, etc.) -### Visibility - -Tink provides standalone static types for potential dangerous operations -(e.g., loading cleartext keys from disk), allowing restricting, monitoring and -logging their usages. +**Visibility** Tink provides standalone static types for potential dangerous +operations (e.g., loading cleartext keys from disk), allowing restricting, +monitoring and logging their usages. ## Maintainers diff --git a/doc/JAVA-HOWTO.md b/doc/JAVA-HOWTO.md new file mode 100644 index 000000000..d1b002d6f --- /dev/null +++ b/doc/JAVA-HOWTO.md @@ -0,0 +1,107 @@ +# Tink Java HOW-TO + +The following subsections present instructions and/or Java-snippets for some +common tasks in [Tink](https://github.com/google/tink). + +## Initializing Tink + +Tink provides customizable initialization, which allows for choosing specific +implementations (identified by _key types_) of desired primitives. This +intialization happens via _registration_ of the implementations. To register +standard implementations of primtives one can use +`registerStandardKeyTypes()`-methods of corresponding factories. Example if one +wants to use the standard implementations of AEAD and MAC primitives offered by +Tink, the initialization would look as follows: + +``` java + import com.google.cloud.crypto.tink.aead.AeadFactory; + import com.google.cloud.crypto.tink.mac.MacFactory; + // (...) + + // Register standard implementations of AEAD and MAC primitives. + AeadFactory.registerStandardKeyTypes(); + MacFactory.registerStandardKeyTypes(); +``` + +For custom initialization the registration proceeds directly via `Registry`-class: + +``` java + import com.google.cloud.crypto.tink.Registry; + import com.google.cloud.crypto.tink.aead.AesCtrHmacAeadKeyManager; + import my.custom.package.aead.MyAeadKeyManager; + // (...) + + // Register only one Tink-implementation of AEAD. + Registry.INSTANCE.registerKeyManager( + AesCtrHmacAeadKeyManager.TYPE_URL, new AesCtrHmacAeadKeyManager()); + + // Register a custom implementation of AEAD. + Registry.INSTANCE.registerKeyManager( + MyAeadKeyManager.TYPE_URL, new MyAeadKeyManager()); + +``` + +## Generating New Key(set)s + +Each `KeyManager`-implementation provides `newKey(..)`-methods that generate new +keys of the corresponding key type. However to avoid accidental leakage of +sensitive key material one should be careful with mixing key(set) generation +with key(set) useage in code. To support the separation between these +activities Tink package provides a command-line tool +called [Tinkey](https://github.com/google/tink/tree/master/tools/tinkey), which +can be used for common key management tasks. Moreover, there is also +[`KmsEncryptedKeysetHandle`](https://github.com/google/tink/blob/master/java/src/main/java/com/google/cloud/crypto/tink/KmsEncryptedKeysetHandle.java)-class, +which enables working with keysets in which the sensitive key material is +encrypted with a KMS-managed key. + +Still, if there is a need to generate a KeysetHandle with fresh key material +directly in Java code, one can use +[`CleartextKeysetHandle`](https://github.com/google/tink/blob/master/java/src/main/java/com/google/cloud/crypto/tink/CleartextKeysetHandle.java)-class: + +``` java + KeysetHandle keysetHandle = CleartextKeysetHandle.generateNew(keyTemplate); +``` + +where `keyTemplate` can be initialized with one of pre-generated templates from +[tools/tinkey/keytemplates](https://github.com/google/tink/tree/master/tools/tinkey/keytemplates)-folder. +Alternatively, one can use also +[`KeysetManager`](https://github.com/google/tink/blob/master/java/src/main/java/com/google/cloud/crypto/tink/KeysetManager.java)-class. + +## Loading Existing Keysets +Via [`KmsEncryptedKeysetHandle`](https://github.com/google/tink/blob/master/java/src/main/java/com/google/cloud/crypto/tink/KmsEncryptedKeysetHandle.java) or +[`CleartextKeysetHandle`](https://github.com/google/tink/blob/master/java/src/main/java/com/google/cloud/crypto/tink/CleartextKeysetHandle.java), + +TODO: write more in this section + +## Creating and Using a Primitive + +After all needed KeyManagers have been registered, one instantiates a primitive +via the corresponding factory. For example, here is how to instantiate and use +AEAD-primitive: + +``` java + import com.google.cloud.crypto.tink.Aead; + import com.google.cloud.crypto.tink.aead.AeadFactory; + import com.google.cloud.crypto.tink.KeysetHandle; + // (...) + + // 1. Get the key material. + KeysetHandle keysetHandle = ...; + // 2. Get the primitive. + Aead aead = AeadFactory.getPrimitive(keysetHandle); + // 3. Use the primitive. + byte[] ciphertext = aead.encrypt(plaintext, aad); +``` + + +## Key Rotation +Via [Tinkey](https://github.com/google/tink/tree/master/tools/tinkey) or +[`KeysetManager`](https://github.com/google/tink/blob/master/java/src/main/java/com/google/cloud/crypto/tink/KeysetManager.java). + +TODO: write more in this section + +## Custom Implementation of a Primitive +TODO: write this section + +## Adding a Custom Primitive +TODO: write this section -- GitLab