0.0
The project is in a healthy, maintained state
BLAKE3ZMQ security mechanism (X25519 + ChaCha20-BLAKE3 AEAD) for the OMQ pure-Ruby ZeroMQ library.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Runtime

 Project Readme

BLAKE3ZMQ

Warning

This is experimental and the gem is not maintained by cryptographers. It has not been independently audited. For production, use CurveZMQ instead.

BLAKE3ZMQ is a security mechanism for OMQ that replaces CurveZMQ with modern primitives:

  • X25519 key exchange (perfect forward secrecy)
  • ChaCha20-BLAKE3 AEAD (32-byte authentication tags)
  • BLAKE3 transcript hash and key derivation

It implements the Protocol::ZMTP::Mechanism::Blake3 class for use with protocol-zmtp.

See RFC.md for the full protocol specification.

Features

  • 4-message handshake (HELLO, WELCOME, INITIATE, READY)
  • Transcript hash binding across all handshake messages; all post-handshake frames (including commands) AEAD-encrypted, unlike CurveZMQ
  • Deterministic nonces (no per-message randomness needed)
  • 32 bytes overhead per message (no wire nonce, no command wrapper)
  • Stateless server until client authentication (cookie mechanism)
  • Mutual authentication or server-only (anonymous client) modes
  • Works out of the box (native C X25519 + Rust AEAD included)
  • Crypto-backend-agnostic (can substitute your own primitives)

Installation

gem "omq-blake3zmq"

Batteries included: ships with x25519 (native C) and chacha20blake3 (Rust native).

Usage

require "omq"
require "omq/blake3zmq"

Crypto = OMQ::Blake3ZMQ::Crypto

# Generate or load keys
server_sk = Crypto::PrivateKey.generate
server_pk = server_sk.public_key.to_s

client_sk = Crypto::PrivateKey.generate
client_pk = client_sk.public_key.to_s

# Server socket
server = OMQ::REP.new
server.mechanism = Protocol::ZMTP::Mechanism::Blake3.server(
  public_key: server_pk,
  secret_key: server_sk.to_s,
  authenticator: ->(peer) { peer.public_key.to_s == client_pk },
)
server.bind("tcp://127.0.0.1:9999")

# Client socket (keys optional — omit for anonymous/ephemeral identity)
client = OMQ::REQ.new
client.mechanism = Protocol::ZMTP::Mechanism::Blake3.client(
  server_key: server_pk,
  public_key: client_pk,
  secret_key: client_sk.to_s,
)
client.connect("tcp://127.0.0.1:9999")

Benchmarks

CurveZMQ (RbNaCl/libsodium) vs BLAKE3ZMQ (Rust native ChaCha20-BLAKE3 + C native X25519).

Ruby 4.0.2, x86_64 Linux.

Handshake latency (100 rounds)

Time Per handshake
CurveZMQ/RbNaCl 226 ms 2.26 ms
BLAKE3ZMQ 120 ms 1.20 ms
Speedup 1.9x

Message encrypt + decrypt throughput (20,000 messages)

Size CurveZMQ/RbNaCl BLAKE3ZMQ Speedup
64 B 8.4 MB/s 16.1 MB/s 1.9x
256 B 38.0 MB/s 51.4 MB/s 1.4x
1 KB 88.1 MB/s 137.5 MB/s 1.6x
4 KB 196.3 MB/s 265.5 MB/s 1.4x
16 KB 289.1 MB/s 387.1 MB/s 1.3x
64 KB 413.3 MB/s 452.4 MB/s 1.1x
128 KB 426.4 MB/s 527.0 MB/s 1.2x
256 KB 428.7 MB/s 538.0 MB/s 1.3x

Full round-trip (handshake + 1,000 messages over UNIXSocket)

Size CurveZMQ/RbNaCl BLAKE3ZMQ Speedup
64 B 69.4 ms (0.9 MB/s) 50.8 ms (1.3 MB/s) 1.4x
1 KB 54.6 ms (18.7 MB/s) 62.6 ms (16.3 MB/s) 0.9x
64 KB 281.7 ms (232.6 MB/s) 242.2 ms (270.6 MB/s) 1.2x

Run benchmarks yourself:

OMQ_DEV=1 bundle exec ruby bench/throughput.rb

Per-message overhead

BLAKE3ZMQ CurveZMQ
Tag size 32 bytes 16 bytes
Counter on wire 0 bytes 8 bytes
Command wrapper none 17 bytes
Total 32 bytes 41 bytes

Development

bundle install
bundle exec rake test

License

ISC