aboutsummaryrefslogtreecommitdiffstats
path: root/library/sodium-plus/docs/SodiumPlus/encrypted-streams.md
blob: 25ed5039c7921e5c344e53de61a91b8fd7d53e5a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
## 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());
})();
```