Skip to content

Commit

Permalink
docs and things
Browse files Browse the repository at this point in the history
  • Loading branch information
ahdinosaur committed Nov 23, 2023
1 parent 5c1aebf commit 48b2a44
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 13 deletions.
42 changes: 37 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
# pull-secretstream

replacement for [`pull-box-stream`](https://github.com/dominictarr/pull-box-stream) using libsodium's [secretstream](https://libsodium.gitbook.io/doc/secret-key_cryptography/secretstream)
Replacement for [`pull-box-stream`](https://github.com/dominictarr/pull-box-stream) using libsodium's [secretstream](https://libsodium.gitbook.io/doc/secret-key_cryptography/secretstream)

## example
Uses a fixed ciphertext block size. (By default: 512 bytes.)

## Example

```js
const { randomBytes } = require('crypto')
const pull = require('pull-stream')
const { KEYBYTES, createEncryptStream, createDecryptStream } = require('pull-secretstream')
const { KEY_SIZE, createEncryptStream, createDecryptStream } = require('pull-secretstream')

// generate a random secret, `KEYBYTES` bytes long.
const key = randomBytes(KEYBYTES)
// generate a random secret, `KEY_SIZE` bytes long.
const key = randomBytes(KEY_SIZE)

const plaintext1 = Buffer.from('hello world')

Expand All @@ -34,3 +36,33 @@ pull(
}),
)
```

## API

### `createEncryptStream(key, ciphertextBlockSize = DEFAULT_BLOCK_SIZE)`

Returns a "through" pull-stream that:

- first sends the secretstream header,
- then encrypts incoming plaintext as secretstream ciphertext (of a fixed block size, padding if necessary),
- and when done, sends a secrestream message marked as the final.

### `createDecryptStream(key, ciphertextBlockSize = DEFAULT_BLOCK_SIZE)`

Returns a "through" pull-stream that:

- first recives the secretstream header,
- then decrypts incoming secretstream ciphertext as plaintext (unpadding if necessary),
- and is done when a secretstream message marked as final is received.

### `DEFAULT_BLOCK_SIZE`

512 bytes

### `KEY_SIZE`

32 bytes

### `getPlaintextBlockSize(ciphertextBlockSize)`

`cipherBlockSize` - 17 bytes (secretstream's additional data)
6 changes: 3 additions & 3 deletions examples/readme.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const { randomBytes } = require('crypto')
const pull = require('pull-stream')
const { KEYBYTES, createEncryptStream, createDecryptStream } = require('../')
const { KEY_SIZE, createEncryptStream, createDecryptStream } = require('../')

// generate a random secret, `KEYBYTES` bytes long.
const key = randomBytes(KEYBYTES)
// generate a random secret, `KEY_SIZE` bytes long.
const key = randomBytes(KEY_SIZE)

const plaintext1 = Buffer.from('hello world')

Expand Down
9 changes: 6 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ createDebug.formatters.h = (v) => {
const debug = createDebug('pull-secretstream')

module.exports = {
KEYBYTES,
KEY_SIZE: KEYBYTES,
DEFAULT_BLOCK_SIZE,
createEncryptStream,
createDecryptStream,
getPlaintextBlockSize,
Expand Down Expand Up @@ -55,6 +56,7 @@ function createEncryptStream(key, ciphertextBlockSize = DEFAULT_BLOCK_SIZE) {
function encryptThroughData(plaintext) {
plaintextBufferList.append(plaintext)

// while we still have enough bytes to send full blocks
while (plaintextBufferList.length >= plaintextBlockSize) {
const plaintextBlock = plaintextBufferList.slice(0, plaintextBlockSize)
plaintextBufferList.consume(plaintextBlockSize)
Expand All @@ -64,6 +66,7 @@ function createEncryptStream(key, ciphertextBlockSize = DEFAULT_BLOCK_SIZE) {
this.queue(ciphertext)
}

// send the remaining as a padded block
if (plaintextBufferList.length > 0) {
const plaintextLength = plaintextBufferList.length
const plaintextBlock = Buffer.alloc(plaintextBlockSize)
Expand All @@ -77,6 +80,7 @@ function createEncryptStream(key, ciphertextBlockSize = DEFAULT_BLOCK_SIZE) {
}
},
function encryptThroughEnd() {
// send a block full of zeros with the final marker
const finalBlock = Buffer.alloc(plaintextBlockSize)
sodium_pad(finalBlock, 0, plaintextBlockSize)
const final = encrypter.final(finalBlock, Buffer.allocUnsafe(plaintextBlockSize + ABYTES))
Expand Down Expand Up @@ -110,6 +114,7 @@ function createDecryptStream(key, ciphertextBlockSize = DEFAULT_BLOCK_SIZE) {
function decryptThroughData(ciphertext) {
ciphertextBufferList.append(ciphertext)

// while we still have enough bytes for full blocks
while (ciphertextBufferList.length >= ciphertextBlockSize) {
const ciphertextBlock = ciphertextBufferList.slice(0, ciphertextBlockSize)
ciphertextBufferList.consume(ciphertextBlockSize)
Expand All @@ -133,14 +138,12 @@ function createDecryptStream(key, ciphertextBlockSize = DEFAULT_BLOCK_SIZE) {
}
},
function decryptThroughEnd() {
/*
if (!decrypter.final) {
this.emit(
'error',
new Error('pull-secretstream/decryptStream: stream ended before final tag'),
)
}
*/
// otherwise the stream should have already been ended.
},
)
Expand Down
4 changes: 2 additions & 2 deletions test/basics.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ const test = require('node:test')
const assert = require('node:assert')
const pull = require('pull-stream')
const { randomBytes } = require('crypto')
const { KEYBYTES, createEncryptStream, createDecryptStream } = require('../')
const { KEY_SIZE, createEncryptStream, createDecryptStream } = require('../')

test('test basic encryptStream and decryptStream', async (t) => {
// generate a random secret, `KEYBYTES` bytes long.
const key = randomBytes(KEYBYTES)
const key = randomBytes(KEY_SIZE)

const plaintext1 = Buffer.from('hello world')

Expand Down

0 comments on commit 48b2a44

Please sign in to comment.