LogoPear Docs
ReferencesHelpers

NoiseSecretStream

Noise-encrypted duplex stream used for Holepunch peer transports.

stable

Secretstream wraps a transport stream in a Noise handshake plus libsodium secretstream encryption. It is the encrypted stream layer used underneath Hyperswarm and related peer transports. For the upstream package, source, and release notes, see the @hyperswarm/secret-stream repository.

Install

npm i hyperswarm-secret-stream

Quickstart

import SecretStream from '@hyperswarm/secret-stream'

const a = new SecretStream(true)
const b = new SecretStream(false)

a.rawStream.pipe(b.rawStream).pipe(a.rawStream)

a.write(Buffer.from('hello encrypted world'))

b.on('data', (data) => {
  console.log(data.toString())
})

API Reference

Constructor and lifecycle

new SecretStream(isInitiator, [rawStream], [options])

src

Make a new stream. isInitiator is a boolean indication whether you are the client or the server. rawStream can be set to an underlying transport stream you want to run the noise stream over.

ParameterTypeDefault
isInitiatorboolean
rawStreamobject
optionsSecretStreamOptions{}
  • Throws: if isInitiator is not a boolean.

s.start(rawStream, [options])

src

Start a SecretStream from a rawStream asynchrously.

ParameterTypeDefaultDescription
rawStreamobjectThe underlying transport stream. If omitted, an internal stream is created and exposed as rawStream.
optionsSecretStreamOptions{}Stream options (the same shape as the constructor's).
  • Returns: void
const s = new SecretStream({
  autoStart: false // call start manually
})

// ... do async stuff or destroy the stream

s.start(rawStream, {
  ... options from above
})

await s.flush()

src

Resolves to true when pending encrypted writes and the underlying raw stream have flushed successfully, or false if the stream closed before that happened.

  • Returns: Promise<boolean>true once flushed, or false if the stream never opened or was destroyed first.
await stream.flush()

Stream configuration

s.setTimeout(ms)

src

Set the stream timeout. If no data is received within a ms window, the stream is auto destroyed.

ParameterTypeDescription
msnumberThe idle timeout in milliseconds (0 disables it).
  • Returns: void
stream.setTimeout(15000)

s.setKeepAlive(ms)

src

Send a heartbeat (empty message) every time the socket is idle for ms milliseconds. Note: If one side calls s.setKeepAlive() and the other does not, then the empty messages will be passed through to the piped stream.

ParameterTypeDescription
msnumberThe keep-alive interval in milliseconds (0 disables it).
  • Returns: void
stream.setKeepAlive(5000)

s.sendKeepAlive()

src

A convenience method that sends an empty message.

  • Returns: void
stream.sendKeepAlive()

Ordered stream I/O

s.write(data)

Writes an ordered payload to be encrypted and sent through the duplex stream, returning the usual writable-stream backpressure boolean.

s.end()

Ends the stream, optionally writing a final ordered payload, following standard writable-stream behavior.

s.on('data', listener)

Receives ordered decrypted payloads as Buffer instances.

Unordered messages

await s.send(buffer)

src

Sends an encrypted unordered message, see udx-native for details. This method silently fails if called before the handshake is complete, or if the underlying rawStream is not a UDX stream (not capable of UDP).

ParameterTypeDescription
bufferBufferThe message to encrypt and send.
  • Returns: Promise<void> — Resolves once the message has been sent.
await stream.send(Buffer.from('ping'))

s.trySend(buffer)

src

Same as send(buffer) but does not return a promise.

ParameterTypeDescription
bufferBufferThe message to encrypt and send.
  • Returns: void
stream.trySend(Buffer.from('ping'))

s.on('message', onmessage)

src

Emmitted when an unordered message is received

Utility methods

s.alloc(len)

src

Returns a writable payload slice backed by a preallocated encrypted output buffer. Write into it, then pass it to stream.write(...).

ParameterTypeDescription
lennumberThe number of plaintext bytes to allocate.
  • Returns: Buffer — A writable buffer of len bytes to fill and then write().
const buf = stream.alloc(4)
buf.write('ping')
stream.write(buf)

s.toJSON()

src

Returns a diagnostic object containing connection state, keys, and any serializable raw-stream metadata.

  • Returns: object — A snapshot with isInitiator, publicKey, remotePublicKey, connected, destroying, destroyed, and rawStream.
console.log(JSON.stringify(stream))

Static helpers

keyPair = SecretStream.keyPair([seed])

Generate a ed25519 key pair.

NoiseSecretStream.id(handshakeHash, isInitiator, id)

src

Derives a 32-byte stream identity from the completed handshake hash, choosing the initiator/responder namespace via isInitiator.

ParameterTypeDescription
handshakeHashBufferThe handshake hash to derive the id from.
isInitiatorbooleanWhether to derive the initiator's id (true) or the responder's (false).
idBufferOptional 32-byte buffer to write the id into; a new one is allocated when omitted.
  • Returns: Buffer — The 32-byte stream id.
const id = SecretStream.id(stream.handshakeHash, stream.isInitiator)

Public properties

s.isInitiator

src

true on the dialing side and false on the accepting side.

  • Returns: boolean

s.rawStream

src

The wrapped transport stream, or a bridge stream when no raw stream was supplied up front.

  • Returns: object

s.publicKey

src

Get the local public key.

s.remotePublicKey

src

Get the remote's public key. Populated after open is emitted.

s.handshakeHash

src

Get the unique hash of this handshake. Populated after open is emitted.

s.connected

src

true once the handshake is complete and the stream has emitted connect.

  • Returns: boolean

s.keepAlive

src

Get the interval (in milliseconds) at which keep-alive messages are sent (0 means none are sent).

  • Returns: number

s.timeout

src

The configured idle-timeout interval in milliseconds.

  • Returns: number

s.enableSend

src

true when unordered send(...) and trySend(...) support is enabled.

  • Returns: boolean

s.opened

src

A promise that resolves to true when the handshake succeeds, or false if the stream closes before opening.

s.rawBytesWritten

src

The number of bytes (measured after encryption) written.

  • Returns: number

s.rawBytesRead

src

The number of bytes (measured before decryption) received.

  • Returns: number

s.userData

src

An arbitrary user-controlled field that higher-level protocols often use to attach transport metadata.

  • Returns: *

Events

s.on('connect', onconnect)

src

Emitted when the handshake is fully done. It is safe to write to the stream immediately though, as data is buffered internally before the handshake has been completed.

s.on('handshake', listener)

src

Fires when the Noise handshake keys and hash have been established.

Types

Handshake

A precomputed Noise handshake to reuse instead of performing one over the stream. Pass it as opts.handshake to adopt the result of a handshake done elsewhere.

PropertyTypeDefaultDescription
txBufferThe transmit (encryption) session key.
rxBufferThe receive (decryption) session key.
hashBufferThe unique hash of the handshake.
publicKeyBufferThe local public key used in the handshake.
remotePublicKeyBufferThe remote peer's public key.

KeyPair

An ed25519 key pair, as produced by {@link NoiseSecretStream.keyPair}.

PropertyTypeDefaultDescription
publicKeyBufferThe 32-byte public key.
secretKeyBufferThe 64-byte secret key.

SecretStreamOptions

Options for creating a SecretStream (also accepted by start()).

PropertyTypeDefaultDescription
patternstringXXWhich Noise handshake pattern to use.
remotePublicKeyBufferThe remote peer's public key, set if the handshake pattern requires it.
keyPairKeyPair|Promise<KeyPair>The local key pair, or a promise resolving to one (the stream waits for it and auto-destroys if it errors).
handshakeHandshakeA handshake performed elsewhere to adopt instead of handshaking over the stream.
keepAlivenumber0Send a keep-alive (empty message) when idle for this many milliseconds (0 disables).
autoStartbooleantrueStart the stream automatically; set false to call start() manually.
enableSendbooleantrue(advanced) Set false to disable the unordered send API.

See also

  • Hyperswarm—the peer-discovery and connection layer that typically hands sockets to Secretstream.
  • HyperDHT—lower-level DHT whose direct keyed connections are also wrapped in Secretstream.
  • Protomux—multiplex higher-level protocols across one framed encrypted stream.
  • Upstream @hyperswarm/secret-stream repository—source, releases, and implementation details.

On this page