blob: 1fbd9adbcbe702cd929e21caa66333600d1e08c4 [file] [view]
# Tink for TypeScript HOW-TO
This document presents instructions and TypeScript code snippets for common
tasks in [Tink](https://github.com/google/tink).
Depending on the specifics of your build setup, you may need to alter these
snippets to use a different import syntax. Both ES modules and UMD are
supported.
WARNING: Tink for TypeScript/JavaScript is still in an alpha state! Breaking
changes are likely.
## Setup instructions
To add Tink to a TypeScript/JavaScript project, just run:
```sh
npm install tink-crypto
```
Or, if you're using Yarn:
```sh
yarn add tink-crypto
```
## Generating new keys and keysets
To take advantage of key rotation and other key management features, you usually
do not work with single keys, but with keysets, which you can use via a wrapper
called `KeysetHandle`. Keysets are just sets of keys with some additional
parameters and metadata. You can generate a new keyset and obtain its handle
using a `KeyTemplate` (example in below code snippet).
To avoid accidental leakage of sensitive key material, you should usually avoid
mixing keyset generation and usage in code. To support the separation of these
activities Tink provides a command-line tool, [Tinkey](TINKEY.md), which can be
used for common key management tasks. Still, if there is a need to generate a
`KeysetHandle` with fresh key material directly in TypeScript code, you can use
`generateNewKeysetHandle`:
```javascript
import {aead, generateNewKeysetHandle} from 'tink-crypto';
const {aes256GcmKeyTemplate} = aead;
(async () => {
const keyTemplate = aes256GcmKeyTemplate()
const keysetHandle = await generateNewKeysetHandle(keyTemplate);
// use the keyset...
})();
```
Currently, key templates are only available for AEAD encryption, digital
signatures, and hybrid encryption.
| Key | Key Template |
: Template : :
: Type : :
| --------- | ---------------------------------------------------------------- |
| AEAD | `aead.aes128GcmKeyTemplate()` |
| AEAD | `aead.aes256GcmKeyTemplate()` |
| AEAD | `aead.aes256GcmNoPrefixKeyTemplate()` |
| Signature | `signature.ecdsaP256KeyTemplate()` |
| Signature | `signature.ecdsaP256IeeeEncodingKeyTemplate()` |
| Signature | `signature.ecdsaP384KeyTemplate()` |
| Signature | `signature.ecdsaP384IeeeEncodingKeyTemplate()` |
| Signature | `signature.ecdsaP521KeyTemplate()` |
| Signature | `signature.ecdsaP521IeeeEncodingKeyTemplate()` |
| Hybrid | `hybrid.eciesP256HkdfHmacSha256Aes128GcmKeyTemplate()` |
| Hybrid | `hybrid.eciesP256HkdfHmacSha256Aes128CtrHmacSha256KeyTemplate()` |
### Storing and loading existing keysets
After generating key material, you might want to persist it to LocalStorage or
IndexedDB, or send it to a server to be stored there. The `binary` and
`binaryInsecure` subpackages can be used to serialize and deserialize keysets to
and from `UInt8Array`. `binary` handles only public keys; `binaryInsecure` can
additionally handle private and symmetric keys. With these, you must be careful
not to leak the raw key material.
```javascript
import {aead, binaryInsecure, generateNewKeysetHandle} from 'tink-crypto';
const {Aead, register, aes256GcmKeyTemplate} = aead;
const {deserializeKeyset, serializeKeyset} = binaryInsecure;
register();
(async () => {
const keysetHandle = await generateNewKeysetHandle(aes256GcmKeyTemplate());
// Serialize keyset to send/store
const serializedKeyset = serializeKeyset(keysetHandle);
const deserializedKeyset = deserializeKeyset(serializedKeyset)
const aead = await deserializedKeyset.getPrimitive(Aead);
// Use deserialization... (i.e. to decrypt a ciphertext)
})();
```
## Obtaining and using primitives
[*Primitives*](PRIMITIVES.md) 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 you choose a desired implementation by using
a key of corresponding type (see the
[this section](KEY-MANAGEMENT.md#key-keyset-and-keysethandle) for details).
A list of primitives and their implementations currently supported by Tink in
TypeScript/JavaScript can be found [here](PRIMITIVES.md#typescriptjavascript).
Note that there are currently a few additional limitations:
* MAC is supported only via the subtle API, not the keyset API.
* It's not possible to generate a fresh new asymmetric keyset using the keyset
API and then use it without going through the subtle API. (The public key is
not directly accessible yet)
### AEAD
AEAD encryption assures the confidentiality and authenticity of the data. This
primitive is CPA secure.
```javascript
// See live on StackBlitz: https://stackblitz.com/edit/tink-typescript?file=index.ts
import {aead, generateNewKeysetHandle} from 'tink-crypto';
const {Aead, register, aes256GcmKeyTemplate} = aead;
register();
(async () => {
const keysetHandle = await generateNewKeysetHandle(aes256GcmKeyTemplate());
const aead = await keysetHandle.getPrimitive(Aead);
const ciphertext = await aead.encrypt(
new TextEncoder().encode('this data needs to be encrypted'),
new TextEncoder().encode('associated data'));
const plaintext = new TextDecoder().decode(await aead.decrypt(
ciphertext, new TextEncoder().encode('associated data')));
console.log('Ciphertext:', ciphertext);
console.log('Plaintext:', plaintext);
})();
```