aboutsummaryrefslogblamecommitdiffstats
path: root/library/sodium-plus/docs/SodiumPlus/encrypted-streams.md
blob: 25ed5039c7921e5c344e53de61a91b8fd7d53e5a (plain) (tree)









































































































































                                                                                                                                                     
## Encrypted Streams

> **See also:** [Libsodium's documentation on its encrypted streams feature](https://download.libsodium.org/doc/secret-key_cryptography/secretstream)

### crypto_secretstream_xchacha20poly1305_init_push()

Initialize a stream for streaming encryption.

**Parameters and their respective types**:

1. `{CryptographyKey}` key

Returns a `Promise` that resolves to an `array` with 2 elements:

1. A 24-byte header that should be included in the encrypted stream.
2. A backend-specific `state`:
    * `LibsodiumWrappers` returns a `number` (a pointer to an internal buffer)
    * `SodiumNative` returns a `CryptoSecretstreamXchacha20poly1305StateWrap`
      object

The `{state}` type annotation below refers to one of the backend-specific state 
types.

You'll typically want to use it with list unpacking syntax, like so:

```
[state, header] = await sodium.crypto_secretstream_xchacha20poly1305_init_push(key);
```

### crypto_secretstream_xchacha20poly1305_init_pull()

Initialize a stream for streaming decryption.

**Parameters and their respective types**:

1. `{CryptographyKey}` key
2. `{Buffer}` header (must be 24 bytes)

Returns a `Promise` that resolves to a backend-specific `state`:

* `LibsodiumWrappers` returns a `number` (a pointer to an internal buffer)
* `SodiumNative` returns a `CryptoSecretstreamXchacha20poly1305StateWrap`
  object

The `{state}` type annotation below refers to one of the backend-specific state 
types.

### crypto_secretstream_xchacha20poly1305_push()

Encrypt some data in a stream.

**Parameters and their respective types**:

1. `{state}` state
2. `{string|Buffer}` message
3. `{string|Buffer}` (optional) additional associated data
4. `{number}` tag (default = 0, see libsodium docs)

Returns a `Promise` that resolves to a `Buffer` containing the ciphertext.

### crypto_secretstream_xchacha20poly1305_pull()

Decrypt some data in a stream.

**Parameters and their respective types**:

1. `{state}` state
2. `{string|Buffer}` ciphertext
3. `{string|Buffer}` (optional) additional associated data
4. `{number}` tag (default = 0, see libsodium docs)

Returns a `Promise` that resolves to a `Buffer` containing
decrypted plaintext.

### crypto_secretstream_xchacha20poly1305_keygen()

Returns a `CryptographyKey` object containing a key appropriate
for the `crypto_secretstream` API.

### crypto_secretstream_xchacha20poly1305_rekey()

Deterministic re-keying of the internal state.

**Parameters and their respective types**:

1. `{state}` state

Returns a `Promise` that resolves to `undefined`. Instead,
the `state` variable is overwritten in-place.

### Example for crypto_secretstream_xchacha20poly1305

```javascript
const fsp = require('fs').promises;
const path = require('path');
const { SodiumPlus } = require('sodium-plus');

let sodium;
(async function () {
    if (!sodium) sodium = await SodiumPlus.auto();

    let key = await sodium.crypto_secretstream_xchacha20poly1305_keygen();
    let pushState, pullState, header;
    [pushState, header] = await sodium.crypto_secretstream_xchacha20poly1305_init_push(key);

    // Get a test input from the text file.
    let longText = await fsp.readFile(path.join(__dirname, 'encrypted-streams.md'));
    let chunk, readUntil;
    let ciphertext = Buffer.concat([header]);

    // How big are our chunks going to be?
    let PUSH_CHUNK_SIZE = await sodium.randombytes_uniform(longText.length - 32) + 32;
    let PULL_CHUNK_SIZE = PUSH_CHUNK_SIZE + sodium.CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES;

    // Encryption...
    for (let i = 0; i < longText.length; i += PUSH_CHUNK_SIZE) {
        readUntil = (i + PUSH_CHUNK_SIZE) > longText.length ? longText.length : i + PUSH_CHUNK_SIZE;
        chunk = await sodium.crypto_secretstream_xchacha20poly1305_push(
            pushState,
            longText.slice(i, readUntil)
        );
        ciphertext = Buffer.concat([ciphertext, chunk]);
    }

    pullState = await sodium.crypto_secretstream_xchacha20poly1305_init_pull(key, header);
    // Decrypt, starting at 24 (after the header, which we already have)
    let decrypted = Buffer.alloc(0);
    for (let i = 24; i < ciphertext.length; i += PULL_CHUNK_SIZE) {
        readUntil = (i + PULL_CHUNK_SIZE) > ciphertext.length ? ciphertext.length : i + PULL_CHUNK_SIZE;
        chunk = await sodium.crypto_secretstream_xchacha20poly1305_pull(
            pullState,
            ciphertext.slice(i, readUntil)
        );
        decrypted = Buffer.concat([decrypted, chunk]);
    }
    console.log(decrypted.toString());
})();
```