jsec  Overview

Jsec provides production-quality TLS/DTLS integration for Janet. The APIs are designed to closely follow Janet's standard conventions:

  • TLS streams implement Janet's full stream interface (ev/read, ev/write, ev/chunk, ev/close) with identical signatures. TLS streams can be used anywhere Janet streams are expected - no special-casing required.

  • DTLS follows Janet's UDP conventions (net/recv-from, net/send-to) for the server-side API, and stream conventions for 1:1 client connections.

This design allows TLS/DTLS to be a drop-in replacement in existing code.

Janet Stream API Compatibility

TLS streams are designed to be fully compatible with Janet's stream API. This means:

  1. Same function signatures: ev/read, ev/write, ev/chunk, ev/close work identically on TLS streams as they do on plain TCP streams.

  2. Drop-in replacement: Code written for net/connect can use tls/connect with no other changes. Generic stream-processing functions work unchanged.

  3. Optional parameter convention: Where Janet stream functions accept one optional parameter (e.g., timeout), jsec accepts either:

    • The original type (number for timeout)
    • A table/struct containing that parameter and optionally TLS-specific options
  4. Only initialization differs: tls/connect vs net/connect and tls/listen~/~tls/accept vs net/listen~/~net/accept have different signatures to accommodate TLS options.

    These work identically on TLS or plain TCP streams:

    (ev/read stream 1024) # Read up to 1024 bytes (ev/write stream "hello") # Write data (ev/chunk stream 100) # Read exactly 100 bytes (ev/close stream) # Close with proper shutdown

    Generic stream function - works with any stream type

    (defn echo-handler stream] (ev/write stream data)))

    Works with plain TCP

    (echo-handler (net/connect "localhost" "8080"))

    Works with TLS - no changes needed

    (echo-handler (tls/connect "localhost" "8443" {:verify false}))

Modules

  • jsec/tls: TCP/TLS operations (Client & Server). Implements full Janet stream interface.
  • jsec/dtls: UDP/DTLS operations (Client & Server). Follows Janet UDP conventions.
  • jsec/cert: Certificate generation utilities.
  • jsec/bio: Basic I/O abstraction (memory BIOs).
  • jsec/crypto: Cryptographic primitives (hashing, signing).

For working examples of all functionality, see the examples directory.

Module: jsec/tls

(tls/new-context opts)

Create a reusable TLS context.

  • opts: Table/struct.
    • :cert: Path to certificate (PEM) or PEM content (string/buffer).
    • :key: Path to private key (PEM) or PEM content (string/buffer).
    • :verify: Boolean (default true for client).
    • :ca-file: Path to CA certificate file or PEM content (string/buffer).
    • :ca-path: Path to CA certificate directory.
    • :security: Security options.
    • :alpn: List of ALPN protocols (e.g. ["h2" "http/1.1"]).
    • :sni: (Server only) Table of hostname -> options for virtual hosting. Example: {"example.com" {:cert "..." :key "..."}}.

Returns: A TLS context object.

Example: See echo_server.janet for context creation and reuse.

(tls/connect host port &opt opts)

Connect to a TLS server.

  • host: String (hostname or IP) or :unix for Unix sockets.
  • port: String (port number) or path for Unix sockets.
  • opts: Optional table/struct OR a TLS context object.
    • If a context is passed, it is used for the connection.
    • If a table is passed:
      • :verify: Boolean (default true). Verify server certificate.
      • :hostname: String. SNI hostname. Defaults to host for TCP, "localhost" for Unix.
      • :verify-hostname: String. Hostname to verify against certificate (defaults to :hostname).
      • :session: Byte string. Session data for resumption (from get-session).
      • :cert: String/buffer. Client certificate (PEM) for mTLS.
      • :key: String/buffer. Client private key (PEM) for mTLS.
      • :trusted-cert: String/buffer. Trust specific cert (for self-signed servers).
      • :buffer-size: Integer. Internal TLS buffer size (default 16384).
      • :tcp-nodelay: Boolean. Enable TCP_NODELAY (default true).
      • :handshake-timing: Boolean. Track handshake duration (default false).
      • :security: Table. Security options (see Security Options).
      • :alpn: List of ALPN protocols.
      • :ca-file: Path to CA certificate file or PEM content (string/buffer).
      • :ca-path: Path to CA certificate directory.

Returns: A TLS stream object.

Examples:

(tls/listen host port &opt opts)

Create a TCP listener. This is a wrapper around net/listen.

  • host: Bind address.
  • port: Bind port.
  • opts: Optional table.
    • :backlog: Integer. Listen backlog (default 1024).

Returns: A listener object.

(tls/accept listener opts)

Accept a connection from a listener and perform the TLS handshake.

  • listener: Listener object from tls/listen.
  • opts: Table/struct OR a TLS context object.
    • If a context is passed, it is used for the connection.
    • If a table is passed:
      • :cert: String. Path to server certificate (PEM) or PEM content (string/buffer).
      • :key: String. Path to private key (PEM) or PEM content (string/buffer).
      • :verify: Boolean (default false). Require and verify client certificate (mTLS).
      • :trusted-cert: String/buffer. Trust specific client certificate (for mTLS with self-signed).
      • :ca: String. Path to CA file for client certificate verification.
      • :buffer-size: Integer. Internal TLS buffer size (default 16384).
      • :tcp-nodelay: Boolean. Enable TCP_NODELAY (default true).
      • :handshake-timing: Boolean. Track handshake duration (default false).
      • :security: Table. Security options.
      • :alpn: List of ALPN protocols.
      • :ca-file: Path to CA certificate file (for mTLS) or PEM content.
      • :ca-path: Path to CA certificate directory (for mTLS).

Returns: A TLS stream object.

(tls/accept-loop listener context handler)

Continuously accept TLS connections on a listener.

  • listener: Listener object from tls/listen.
  • context: TLS context object OR options table (same as tls/accept).
    • Can include :buffer-size, :tcp-nodelay, :handshake-timing.
  • handler: Function taking a TLS stream.

Returns: The listener stream (when closed).

(tls/upgrade stream hostname &opt opts)

Upgrade an existing plaintext stream to TLS (STARTTLS).

  • stream: Existing connected JanetStream.
  • hostname: String. SNI hostname.
  • opts: Optional table (same as connect).

Returns: A TLS stream object. Note: The original stream is consumed.

Example: See starttls_smtp.janet for SMTP STARTTLS upgrade.

(tls/wrap stream &opt hostname-or-opts opts)

Wrap an existing stream with TLS. Used for both client and server modes.

Client mode (provides hostname):

  • stream: Existing connected JanetStream.
  • hostname-or-opts: String. SNI hostname.
  • opts: Optional table:
    • :verify: Boolean (default true). Verify server certificate.
    • :cert: String/buffer. Client certificate (PEM) for mTLS.
    • :key: String/buffer. Client private key (PEM) for mTLS.
    • :trusted-cert: String/buffer. Trust specific cert (for self-signed).
    • :session: Buffer. Session data for resumption.
    • :buffer-size: Integer. Internal TLS buffer size.
    • :tcp-nodelay: Boolean. Enable TCP_NODELAY (default true).
    • :handshake-timing: Boolean. Track handshake duration (default false).
    • :security: Table. Security options.
    • :alpn: List of ALPN protocols.

Server mode (provides cert/key):

  • stream: Existing connected JanetStream from :accept.
  • hostname-or-opts: Table/struct with:
    • :cert: String/buffer. Server certificate (PEM). Required.
    • :key: String/buffer. Server private key (PEM). Required.
    • :verify: Boolean. If true, require client certificate (mTLS).
    • :trusted-cert: String/buffer. Trust specific client cert.
    • :ca: String. Path to CA file for client cert verification.
    • :buffer-size: Integer. Internal TLS buffer size.
    • :tcp-nodelay: Boolean. Enable TCP_NODELAY (default true).
    • :handshake-timing: Boolean. Track handshake duration (default false).
    • :security: Table. Security options.
    • :alpn: List of ALPN protocols.

Returns: A TLS stream object.

Examples:

# Client mode - connect with client certificate (mTLS)
(def tls (tls/wrap tcp-stream "example.com" 
           {:cert client-cert :key client-key :verify false}))

# Server mode - require client certificate (mTLS)
(def tls (tls/wrap accepted-stream 
           {:cert server-cert :key server-key 
            :verify true :trusted-cert client-cert}))

Stream Methods (Janet Stream API Compatible)

TLS streams implement Janet's standard stream interface. They work with:

  • ev/read / :read - Read data from the stream
  • ev/write / :write - Write data to the stream
  • ev/chunk / :chunk - Read exactly n bytes or until EOF
  • ev/close / :close - Close with proper TLS shutdown

(ev/read stream n &opt buf timeout)

Read up to n bytes from the TLS stream.

  • stream: TLS stream object
  • n: Maximum bytes to read
  • buf: Optional buffer to read into
  • timeout: Optional timeout in seconds

Returns: Buffer with data, or nil on EOF.

(ev/write stream data &opt timeout)

Write data to the TLS stream.

  • stream: TLS stream object
  • data: String or buffer to write
  • timeout: Optional timeout in seconds

Returns: nil

(ev/chunk stream n &opt buf timeout)

Read exactly n bytes, or until EOF.

  • stream: TLS stream object
  • n: Exact number of bytes to read
  • buf: Optional buffer to read into
  • timeout: Optional timeout in seconds

Returns: Buffer with data.

(ev/close stream)

Close the TLS stream with proper RFC-compliant shutdown.

Performs async bidirectional close_notify exchange before closing the underlying transport. Safe to use with Janet's with macro.

  • stream: TLS stream object

Note: For unresponsive peers, use (:close stream true) to force immediate close without TLS shutdown.

TLS Stream Methods (via jsec/tls-stream)

These methods are available on TLS stream objects. Access via method syntax (:method stream args...) or import jsec/tls-stream for function versions.

Connection Information

  • (:connection-info stream) or (tls-stream/connection-info stream) Returns a struct with connection details:

    • :version: TLS version (e.g., "TLSv1.3")
    • :cipher: Cipher suite name
    • :cipher-bits: Cipher strength
    • :alpn: Negotiated ALPN protocol
    • :server-name: SNI hostname
  • (:version stream) or (tls-stream/version stream) Returns TLS version string (e.g., "TLSv1.3")

  • (:cipher stream) or (tls-stream/cipher stream) Returns cipher suite name

  • (:cipher-bits stream) or (tls-stream/cipher-bits stream) Returns cipher bit strength as integer

Session Management

  • (:session-reused? stream) or (tls-stream/session-reused? stream) Returns true if session was resumed

  • (:get-session stream) or (tls-stream/get-session stream) Returns session data (byte string) for resumption

  • (:set-session stream data) or (tls-stream/set-session stream data) Sets session data (usually passed in connect options instead)

TLS Operations

  • (:key-update stream) or (tls-stream/key-update stream) Request TLS 1.3 key update (post-handshake key rotation)

  • (:renegotiate stream) or (tls-stream/renegotiate stream) Request TLS 1.2 renegotiation (disabled by default for security)

  • (:set-ocsp-response stream data) or (tls-stream/set-ocsp-response stream data) Set OCSP stapling response

  • (:shutdown stream &opt force) or (tls-stream/shutdown stream &opt force) Perform TLS shutdown. If force is true, skip close_notify.

Certificate Trust

  • (tls-stream/trust-cert ctx cert-pem) Add a trusted certificate to a context. Used for trusting self-signed certs.

Example: See session_resumption.janet for session management. Example: See tls_key_update.janet for key update usage. Example: See connection_info.janet for connection info retrieval.

Module: jsec/dtls

DTLS provides TLS security for UDP datagrams. The API design:

  • Server-side: Follows Janet's UDP conventions (net/recv-from, net/send-to) for multiplexed peer handling on a single socket.
  • Client-side: 1:1 connections with stream-like read~/~write for simplicity.

Both DTLSServer and DTLSClient embed JanetStream and expose methods via the standard (:method obj args...) syntax, matching Janet's stream patterns.

Stream Method Access

Both DTLSServer and DTLSClient support method dispatch:

# Server methods
(:recv-from server nbytes buf)
(:send-to server addr data)
(:close server)
(:localname server)

# Client methods  
(:read client nbytes)
(:write client data)
(:close client)

Server API (UDP-style, multiple peers)

(dtls/listen host port &opt opts)

Create a DTLS server bound to an address.

  • host: Bind address (string)
  • port: Bind port (integer or string)
  • opts: Table
    • :cert: Server certificate (PEM string). Required.
    • :key: Server private key (PEM string). Required.
    • :verify: Boolean (default false). Request client certificates (mTLS).
    • :ca: CA certificates for client verification.
    • :session-timeout: Session timeout in seconds (default 300).

Returns: A DTLS server object.

(dtls/recv-from server nbytes buf &opt timeout-or-opts)

Receive a datagram from any peer. Handles DTLS handshakes transparently.

  • server: DTLS server object
  • nbytes: Maximum bytes to receive
  • buf: Buffer to receive data into
  • timeout-or-opts: Number (timeout in seconds) or table {:timeout n}

Returns: Peer address object, or nil on timeout.

Matches Janet's net/recv-from convention.

(dtls/send-to server addr data &opt timeout)

Send a datagram to a specific peer.

  • server: DTLS server object
  • addr: Peer address (from recv-from)
  • data: Data to send (string or buffer)
  • timeout: Optional timeout in seconds

Returns: Number of bytes sent.

(dtls/close-server server &opt force)

Close the server and all sessions.

  • server: DTLS server object
  • force: If true, skip close_notify alerts (default false)

(dtls/localname server)

Get the local address the server is bound to.

Returns: [host port] tuple.

Client API (1:1 connection)

(dtls/connect host port &opt opts)

Create a DTLS client connection. Performs handshake.

  • host: String (hostname or IP address)
  • port: Integer or string (port number)
  • opts: Optional table
    • :verify: Boolean (default true). Verify server certificate.
    • :cert: Client certificate for mTLS (PEM string).
    • :key: Client private key for mTLS (PEM string).
    • :ca: CA certificate (PEM string).
    • :sni: Server name for SNI (defaults to host).
    • :verify-hostname: Hostname to verify against cert.
    • :handshake-timing: Boolean. Track handshake duration.

Returns: A DTLS client object.

(dtls/read client n &opt buf timeout)

Read a datagram from the connection.

  • client: DTLS client object
  • n: Maximum bytes to read
  • buf: Optional buffer to read into
  • timeout: Optional timeout in seconds

Returns: Buffer with data, or nil on EOF.

(dtls/write client data &opt timeout)

Write a datagram to the connection.

  • client: DTLS client object
  • data: Data to send (string or buffer)
  • timeout: Optional timeout in seconds

Returns: Number of bytes written.

(dtls/close client &opt force)

Close the client connection.

  • client: DTLS client object
  • force: If true, skip close_notify (default false)

Address Utilities

  • (dtls-stream/address host port): Create an address object.
  • (dtls-stream/address-host addr): Get host string from address.
  • (dtls-stream/address-port addr): Get port number from address.
  • (dtls-stream/address? x): Check if x is a DTLS address object.

DTLS Stream Methods (via jsec/dtls-stream)

These methods are available on DTLS server and client objects. Access via method syntax (:method obj args...) or import jsec/dtls-stream for function versions.

Connection Information (Client)

  • (:connection-info client) or (dtls-stream/connection-info client) Returns a struct with connection details:

    • :version: DTLS version (e.g., "DTLSv1.2")
    • :cipher: Cipher suite name
    • :cipher-bits: Cipher strength
  • (:version client) or (dtls-stream/version client) Returns DTLS version string

  • (:cipher client) or (dtls-stream/cipher client) Returns cipher suite name

  • (:cipher-bits client) or (dtls-stream/cipher-bits client) Returns cipher bit strength

  • (:peername client) or (dtls-stream/peername client) Returns peer address as [host port] tuple

Session Management (Client)

  • (:session-reused? client) or (dtls-stream/session-reused? client) Returns true if session was resumed

  • (:get-session client) or (dtls-stream/get-session client) Returns session data for resumption

  • (:set-session client data) or (dtls-stream/set-session client data) Sets session data

DTLS Operations

  • (:shutdown client &opt force) or (dtls-stream/shutdown client &opt force) Perform DTLS shutdown. If force is true, skip close_notify.

  • (:chunk client n &opt buf timeout) or (dtls-stream/chunk client ...) Read exactly n bytes (for client connections)

Certificate Trust

  • (dtls-stream/trust-cert ctx cert-pem) Add a trusted certificate to a context.

Upgrade (STARTTLS equivalent)

  • (dtls-stream/upgrade stream &opt opts) Upgrade an existing UDP socket to DTLS.

Example: See dtls_echo.janet for complete DTLS usage. Example: See dtls_session_resumption.janet for session resumption. Example: See dtls_connection_info.janet for connection info.

Module: jsec/cert

(cert/generate-self-signed-cert opts)

Generate a self-signed X.509 certificate and private key.

  • opts: Table.
    • :common-name: String (default "localhost").
    • :days-valid: Integer (default 365).
    • :bits: Integer, RSA key size (default 2048, only for RSA).
    • :key-type: Keyword, key algorithm (default :rsa). Supported: :rsa, :ec-p256, :ec-p384, :ec-p521, :ed25519
    • :country: String (default "US").
    • :organization: String (default "Test").

Note: Generated certificates have CA:TRUE basic constraint set.

Returns: Struct {:cert "PEM..." :key "PEM..."}.

(cert/generate-self-signed-from-key key-pem opts)

Generate a self-signed certificate using an existing private key.

  • key-pem: Existing private key in PEM format.
  • opts: Table.
    • :common-name: String (default "localhost").
    • :days-valid: Integer (default 365).
    • :country: String (default "US").
    • :organization: String (default "Test").

Note: Generated certificates have CA:TRUE basic constraint set.

Returns: Certificate PEM string.

(cert/parse cert-pem)

Parse an X.509 certificate and return its details.

  • cert-pem: Certificate in PEM format.

Returns: Table with:

  • :version - Certificate version (1, 2, or 3)
  • :serial - Serial number as hex string
  • :subject - Subject fields {:cn :o :ou :c :st :l :email :dn}
  • :issuer - Issuer fields (same structure as subject)
  • :not-before - Validity start (Unix timestamp)
  • :not-after - Validity end (Unix timestamp)
  • :public-key - Key info {:type :bits :curve}
  • :san - Subject Alternative Names array
  • :key-usage - Key usage array
  • :ext-key-usage - Extended key usage array
  • :is-ca - Boolean indicating if cert is a CA
  • :fingerprint-sha256 - SHA-256 fingerprint
  • :fingerprint-sha1 - SHA-1 fingerprint
  • :signature-algorithm - Signature algorithm name
  • :pem - Original PEM data

(cert/fingerprint cert-pem &opt algorithm)

Calculate certificate fingerprint.

  • cert-pem: Certificate in PEM format.
  • algorithm: Hash algorithm (default :sha256). Supported: :sha256, :sha384, :sha512, :sha1.

Returns: Fingerprint as hex string with colons.

(cert/verify-signature cert-pem issuer-cert-pem)

Verify that a certificate was signed by the issuer.

  • cert-pem: Certificate to verify.
  • issuer-cert-pem: Issuer's certificate.

Returns: Boolean (true if signature valid).

(cert/verify-chain cert-pem &opt opts)

Verify a certificate against a trust chain.

  • cert-pem: Certificate to verify.
  • opts: Optional table.
    • :chain - Array of intermediate certificate PEMs.
    • :trusted - Array of trusted root certificate PEMs.
    • :trusted-dir - Directory of trusted certs (OpenSSL hash format).
    • :purpose - Certificate purpose (:server-auth, :client-auth, :code-signing, :email-protection, :timestamp, :any).
    • :hostname - Verify hostname in SAN/CN.
    • :time - Verify at specific Unix timestamp.
    • :check-crl - Enable CRL checking.
    • :crl - CRL PEM to check against.

Returns: Table:

  • {:valid true :chain [<pem> ...]} on success
  • {:valid false :error "message" :depth N} on failure

(cert/build-chain cert-pem intermediates trusted)

Build a certificate chain from cert to trusted root.

  • cert-pem: Certificate to start chain from.
  • intermediates: Array of intermediate PEMs or single PEM with multiple certs.
  • trusted: Array of trusted root PEMs or single PEM.

Returns: Array of PEM strings from cert to root, or nil if chain can't be built.

Example: See cert_gen.janet for certificate generation usage.

Module: jsec/ca

The CA module provides a complete Certificate Authority implementation for managing X.509 certificates.

For detailed examples, tutorials, and advanced usage patterns, see CA.org.

(ca/generate &opt opts)

Generate a new self-signed root CA.

  • opts: Optional table.
    • :common-name - CA common name (default "Root CA").
    • :days-valid - Validity period in days (default 3650).
    • :key-type - Key type: :ec-p256, :ec-p384, :rsa-2048, etc. (default :ec-p256).
    • :serial - Starting serial number for issued certs (default 1).
    • :track-issued - Track issued certificates in memory (default false).
    • :organization - Organization name.
    • :country - Two-letter country code.

Returns: CA object.

(ca/generate-intermediate parent-ca &opt opts)

Generate an intermediate CA signed by a parent CA.

  • parent-ca: Parent CA object.
  • opts: Same as ca/generate plus:
    • :path-length - Maximum sub-CAs allowed (default 0).

Returns: CA object.

(ca/create cert-pem key-pem &opt opts)

Create a CA from existing certificate and private key.

  • cert-pem: CA certificate in PEM format.
  • key-pem: CA private key in PEM format.
  • opts: Optional table.
    • :serial - Current serial number (for restoration).
    • :track-issued - Track issued certificates.

Returns: CA object.

(:issue ca &opt opts) / (ca/issue ca &opt opts)

Generate a new certificate (key + cert in one step).

  • ca: CA object.
  • opts: Optional table.
    • :common-name - Certificate common name. Required.
    • :san - Subject Alternative Names array (e.g., ["DNS:example.com" "IP:1.2.3.4"]).
    • :days-valid - Validity period (default 365).
    • :key-type - Key type (default :ec-p256).
    • :extended-key-usage - e.g., "serverAuth", "clientAuth".
    • :key-usage - Override key usage extension.
    • :organization - Organization name.
    • :country - Country code.

Returns: {:cert <pem> :key <pem>}

(:sign-csr ca csr-pem &opt opts) / (ca/sign ca csr-pem &opt opts)

Sign a Certificate Signing Request.

  • ca: CA object.
  • csr-pem: CSR in PEM format.
  • opts: Optional table.
    • :days-valid - Validity period (default 365).
    • :serial - Override serial number.
    • :copy-extensions - Copy extensions from CSR (default false).
    • :extended-key-usage - Extended key usage.
    • :san - Subject Alternative Names.

Returns: Certificate in PEM format.

(:get-cert ca) / (ca/get-cert ca)

Get the CA's certificate in PEM format.

(:get-serial ca) / (ca/get-serial ca)

Get the CA's current serial number. Use for persistence.

(:set-serial ca serial) / (ca/set-serial ca serial)

Set the CA's serial number. Use to restore from persistence.

(:revoke ca serial &opt reason) / (ca/revoke ca serial &opt reason)

Revoke a certificate by serial number.

  • serial: Certificate serial number.
  • reason: Revocation reason keyword (:key-compromise, :superseded, etc.).

(:generate-crl ca &opt opts) / (ca/crl ca &opt opts)

Generate a Certificate Revocation List.

  • opts: Optional table.
    • :days-valid - CRL validity period (default 30).
    • :revoked - Additional revocations array.

Returns: CRL in PEM format.

(:get-revoked ca) / (ca/get-revoked ca)

Get list of revoked certificate serials.

Returns: Array of {:serial N :reason <kw>} tables.

(ca/parse-ocsp-request request-bytes)

Parse an OCSP request (DER-encoded bytes).

Returns: {:issuer-name-hash :issuer-key-hash :serial :nonce}

(:create-ocsp-response ca request-info status &opt opts)

Create an OCSP response for a certificate status query.

  • request-info: Parsed request from ca/parse-ocsp-request.
  • status: :good, :revoked, or :unknown.
  • opts: Optional table.
    • :revocation-time - When revoked (required if status :revoked).
    • :revocation-reason - Why revoked.
    • :this-update - Response validity start (default: now).
    • :next-update - Response validity end (default: +1 day).
    • :include-nonce - Echo nonce from request (default true).

Returns: DER-encoded OCSP response bytes.

(:is-tracking ca) / (ca/is-tracking ca)

Check if the CA is tracking issued certificates.

(:get-issued ca) / (ca/get-issued ca)

Get list of issued certificates (only if tracking enabled).

Returns: Array of PEM certificates, or nil if tracking disabled.

Module: jsec/bio

BIO (Basic I/O) provides OpenSSL's I/O abstraction layer for in-memory operations.

(bio/new-mem)

Create a memory BIO for in-memory I/O operations.

Returns: A BIO object.

(bio/read bio nbytes)

Read from a BIO.

  • bio: BIO object
  • nbytes: Maximum bytes to read

Returns: Buffer with data, or nil if no data available.

(bio/write bio data)

Write to a BIO.

  • bio: BIO object
  • data: Data to write (string or buffer)

Returns: Number of bytes written.

(bio/to-string bio)

Read all pending data from a BIO as a string.

  • bio: BIO object

Returns: String with all pending data.

(bio/close bio)

Free a BIO object and release its resources.

  • bio: BIO object

Example: See bio_memory.janet and custom_bio_transport.janet.

Module: jsec/crypto

Hashing and Message Authentication

(crypto/digest algorithm data)

Compute a cryptographic hash.

  • algorithm: String ("sha256", "sha384", "sha512", "sha1", "md5", etc.)
  • data: Data to hash (string or buffer)

Returns: Buffer with hash bytes.

(crypto/hmac algorithm key data)

Compute HMAC (Hash-based Message Authentication Code).

  • algorithm: Hash algorithm ("sha256", etc.)
  • key: Secret key (string or buffer)
  • data: Data to authenticate (string or buffer)

Returns: Buffer with HMAC bytes.

Key Generation and Management

(crypto/generate-key alg &opt bits)

Generate a private key in PEM format.

  • alg: Keyword for key algorithm:
    • :rsa - RSA key (optional bits param, default 2048)
    • :ed25519 - Ed25519 key (signing)
    • :x25519 - X25519 key (key exchange/ECDH)
    • :ec-p256 or :p256 - EC P-256 curve
    • :ec-p384 or :p384 - EC P-384 curve
    • :ec-p521 or :p521 - EC P-521 curve
  • bits: Optional key size for RSA (default 2048)

Returns: PEM-encoded private key string.

(crypto/export-public-key private-key-pem)

Extract public key from a private key.

  • private-key-pem: PEM-encoded private key string

Returns: PEM-encoded public key string.

Signing and Verification

(crypto/sign key-pem data)

Sign data with a private key.

  • key-pem: Private key in PEM format
  • data: Data to sign (string or buffer)

Returns: Signature buffer.

(crypto/verify key-pem data signature)

Verify a signature.

  • key-pem: Key in PEM format (public or private)
  • data: Original data
  • signature: Signature to verify

Returns: Boolean (true if valid).

Key Derivation

(crypto/hkdf algorithm key salt info length)

HKDF (HMAC-based Key Derivation Function).

  • algorithm: Hash algorithm ("sha256", etc.)
  • key: Input key material
  • salt: Salt value (can be empty string)
  • info: Context/application info
  • length: Desired output length in bytes

Returns: Derived key buffer.

(crypto/pbkdf2 algorithm password salt iterations length)

PBKDF2 (Password-Based Key Derivation Function 2).

  • algorithm: Hash algorithm
  • password: Password string
  • salt: Salt value
  • iterations: Number of iterations (minimum 10000 recommended)
  • length: Desired output length in bytes

Returns: Derived key buffer.

Random Data

(crypto/random-bytes n)

Generate cryptographically secure random bytes.

  • n: Number of bytes

Returns: Buffer with random bytes.

Certificate Signing Requests

(crypto/generate-csr private-key-pem options)

Generate a Certificate Signing Request (CSR).

  • private-key-pem: Private key in PEM format
  • options: Table with subject and options:
    • :common-name - CN field (required for most CAs)
    • :country - C field (2-letter code)
    • :state - ST field
    • :locality - L field
    • :organization - O field
    • :organizational-unit - OU field
    • :email - emailAddress field
    • :san - Array of Subject Alt Names (e.g. ["DNS:example.com" "IP:1.2.3.4"])
    • :digest - Signing digest (default :sha256)

Returns: PEM-encoded CSR string.

(crypto/parse-csr csr-pem)

Parse a PEM-encoded CSR.

  • csr-pem: CSR in PEM format

Returns: Table with CSR information.

Challenge-Response

(crypto/generate-challenge &opt length)

Generate a random challenge for authentication protocols.

  • length: Challenge length in bytes (default 32)

Returns: Buffer with random challenge.

CMS/PKCS#7 Operations

For SCEP/ACME foundations and secure message exchange.

(crypto/cms-sign data cert key &opt opts)

Sign data using CMS (Cryptographic Message Syntax).

  • data: Data to sign
  • cert: Signer certificate (PEM)
  • key: Signer private key (PEM)
  • opts: Optional table
    • :detached: Boolean. If true, create detached signature.

Returns: CMS signed data (DER or PEM based on input).

(crypto/cms-verify cms-data &opt opts)

Verify a CMS signature.

  • cms-data: CMS signed data
  • opts: Optional table
    • :ca: CA certificate for verification
    • :detached: Original data if signature is detached

Returns: Table {:valid true/false :content data :certs [...]}

(crypto/cms-encrypt data certs &opt opts)

Encrypt data for recipients using CMS.

  • data: Data to encrypt
  • certs: Array of recipient certificates (PEM)
  • opts: Optional table
    • :cipher: Cipher to use (default "aes-256-cbc")

Returns: CMS encrypted data.

(crypto/cms-decrypt cms-data cert key)

Decrypt CMS encrypted data.

  • cms-data: Encrypted CMS data
  • cert: Recipient certificate (PEM)
  • key: Recipient private key (PEM)

Returns: Decrypted data buffer.

(crypto/cms-certs-only certs)

Create a CMS certs-only message (certificate chain).

  • certs: Array of certificates (PEM)

Returns: CMS data containing certificates.

(crypto/cms-get-certs cms-data)

Extract certificates from CMS data.

  • cms-data: CMS signed or certs-only data

Returns: Array of PEM-encoded certificates.

Base64 Encoding

(crypto/base64-encode data)

Base64 encode data.

Returns: Base64 string.

(crypto/base64-decode data)

Base64 decode data.

Returns: Decoded buffer.

(crypto/base64url-encode data)

URL-safe Base64 encode (for JWT, etc.).

Returns: Base64url string.

(crypto/base64url-decode data)

URL-safe Base64 decode.

Returns: Decoded buffer.

Example: See crypto_signing.janet for signing operations. Example: See crypto_operations.janet for comprehensive crypto usage.

Symmetric Encryption (AEAD)

(crypto/encrypt algo key nonce plaintext &opt aad)

Encrypt data using authenticated encryption (AEAD).

  • algo: Cipher algorithm keyword
    • :aes-128-gcm - AES-128 in GCM mode (16-byte key, 12-byte nonce)
    • :aes-256-gcm - AES-256 in GCM mode (32-byte key, 12-byte nonce)
    • :chacha20-poly1305 - ChaCha20-Poly1305 (32-byte key, 12-byte nonce)
    • :aes-128-cbc - AES-128 in CBC mode (16-byte key, 16-byte IV)
    • :aes-256-cbc - AES-256 in CBC mode (32-byte key, 16-byte IV)
  • key: Encryption key (buffer, correct length for algorithm)
  • nonce: Nonce/IV (buffer, correct length for algorithm)
  • plaintext: Data to encrypt
  • aad: Optional additional authenticated data (AEAD only)

Returns: Struct {:ciphertext <buffer> :tag <buffer>}

IMPORTANT: Never reuse a nonce with the same key!

(crypto/decrypt algo key nonce ciphertext tag &opt aad)

Decrypt data using authenticated encryption.

  • algo: Same as encrypt
  • key: Encryption key
  • nonce: Same nonce used for encryption
  • ciphertext: Encrypted data
  • tag: Authentication tag (required for AEAD, nil for CBC)
  • aad: Must match AAD used during encryption

Returns: Decrypted plaintext buffer.

Errors: If authentication fails (tag mismatch).

(crypto/generate-nonce algo)

Generate a random nonce suitable for the specified cipher.

  • algo: Cipher algorithm keyword

Returns: Buffer of appropriate length.

(crypto/cipher-info algo)

Get information about a cipher algorithm.

  • algo: Cipher algorithm keyword

Returns: Struct with cipher details:

  • :name - Algorithm name
  • :key-length - Required key length in bytes
  • :nonce-length - Required nonce/IV length in bytes
  • :tag-length - Authentication tag length (AEAD)
  • :aead - Boolean indicating if cipher is AEAD

Example: See symmetric_encryption.janet for AEAD encryption.

RSA Encryption

(crypto/rsa-encrypt key-pem plaintext &opt opts)

Encrypt data with RSA public key.

  • key-pem: Public or private key in PEM format
  • plaintext: Data to encrypt
  • opts: Optional table
    • :padding - Padding mode (default :oaep-sha256)
      • :oaep-sha256 (recommended)
      • :oaep-sha384
      • :oaep-sha512
      • :oaep-sha1 (legacy)
      • :pkcs1 (legacy, NOT recommended)

Returns: Encrypted ciphertext buffer.

Note: RSA can only encrypt limited data based on key size and padding. Use rsa-max-plaintext to check limits. For larger data, use hybrid encryption.

(crypto/rsa-decrypt key-pem ciphertext &opt opts)

Decrypt data with RSA private key.

  • key-pem: Private key in PEM format
  • ciphertext: Encrypted data
  • opts: Must match encryption options

Returns: Decrypted plaintext buffer.

(crypto/rsa-max-plaintext key-pem &opt opts)

Get maximum plaintext size for RSA encryption.

  • key-pem: Key in PEM format
  • opts: Same as rsa-encrypt

Returns: Maximum bytes that can be encrypted.

Example: See rsa_encryption.janet for RSA encryption and hybrid encryption.

Key/Certificate Format Conversion

(crypto/convert-key key-data target-format &opt opts)

Convert a key between formats.

  • key-data: Key in any supported format
  • target-format: Keyword
    • :pem - PEM format
    • :der - DER (binary) format
    • :pkcs8 - PKCS#8 PEM format
    • :pkcs8-der - PKCS#8 DER format
  • opts: Optional table
    • :password - Password for encrypted PKCS#8 output

Returns: Key in target format.

(crypto/convert-cert cert-data target-format)

Convert a certificate between PEM and DER formats.

  • cert-data: Certificate data
  • target-format: :pem or :der

Returns: Certificate in target format.

(crypto/detect-format data)

Detect if data is PEM or DER format.

Returns: :pem or :der

(crypto/load-key key-pem &opt password)

Load a private key, optionally decrypting it.

  • key-pem: Key in PEM format
  • password: Password if key is encrypted

Returns: Decrypted key in PEM format.

(crypto/export-key key-pem &opt opts)

Export a private key, optionally encrypting it.

  • key-pem: Key in PEM format
  • opts: Optional table
    • :password - Password for encryption
    • :cipher - Encryption cipher (:aes-256-cbc, :aes-128-cbc, :des-ede3-cbc)

Returns: Key in PEM format.

(crypto/key-info key-pem)

Get metadata about a key without needing the password.

Returns: Table with:

  • :type - :rsa, :ec, :ed25519, :x25519, etc.
  • :bits - Key size in bits
  • :curve - EC curve name (for EC keys)
  • :encrypted - True if password-protected

Example: See format_conversion.janet for format conversion.

PKCS#12 Operations

(crypto/create-pkcs12 cert-pem key-pem opts)

Create a PKCS#12 (PFX) bundle.

  • cert-pem: Certificate in PEM format
  • key-pem: Private key in PEM format
  • opts: Table
    • :password - Required password for bundle
    • :chain - Optional array of CA certificate PEMs
    • :friendly-name - Optional friendly name attribute

Returns: PKCS#12 bundle bytes (DER format).

(crypto/parse-pkcs12 pfx-data password)

Parse a PKCS#12 bundle.

  • pfx-data: PKCS#12 data (from file or create-pkcs12)
  • password: Bundle password

Returns: Table with:

  • :cert - Certificate PEM
  • :key - Private key PEM
  • :chain - Array of CA certificate PEMs
  • :friendly-name - Friendly name if present

Example: See pkcs12_operations.janet for PKCS#12 usage.

Elliptic Curve Point Operations

Low-level EC point arithmetic for custom protocols, threshold cryptography, zero-knowledge proofs, and Bitcoin/Ethereum cryptography.

(crypto/ec-generate-scalar curve)

Generate a random scalar in [1, order-1] for the curve.

  • curve: Curve identifier
    • :p-256 (secp256r1) - NIST 256-bit
    • :p-384 (secp384r1) - NIST 384-bit
    • :p-521 (secp521r1) - NIST 521-bit
    • :secp256k1 - Bitcoin/Ethereum curve

Returns: Big-endian byte buffer.

(crypto/ec-point-mul curve scalar &opt point)

Scalar multiplication on elliptic curve.

  • curve: Curve identifier
  • scalar: Big-endian byte buffer
  • point: Optional {:x <buffer> :y <buffer>}. If nil, multiplies generator G.

Returns: {:x <buffer> :y <buffer>}

(crypto/ec-point-add curve point1 point2)

Point addition on elliptic curve.

Returns: {:x <buffer> :y <buffer>}

(crypto/ec-point-to-bytes curve point &opt opts)

Serialize EC point to SEC1 format.

  • opts: Optional table
    • :compressed - If true, use compressed format

Returns: Bytes buffer.

(crypto/ec-point-from-bytes curve bytes)

Deserialize EC point from SEC1 format.

Returns: {:x <buffer> :y <buffer>}

Example: See ec_point_operations.janet for EC operations.

Module: jsec/utils

Utility functions for introspection and backend detection.

(utils/ssl-backend)

Returns the SSL backend keyword: :openssl or :libressl.

Useful for conditional code paths based on the SSL library.

(utils/ssl-version)

Returns detailed SSL library version info.

Returns: Struct with:

  • :backend - :openssl or :libressl
  • :version - Version string (e.g., "OpenSSL 3.0.2" or "LibreSSL 4.0.0")
  • :number - Numeric version for comparison

Additional TLS Stream Methods

(tls/get-handshake-time stream)

Get the TLS handshake duration.

Returns: Handshake time in seconds as floating-point number, or nil if handshake hasn't completed.

Requires :handshake-timing true option during connection.

Additional DTLS Functions

(dtls/new-context &opt opts)

Create a reusable DTLS context.

  • opts: Optional table.
    • :cert - Certificate (PEM string or file path).
    • :key - Private key (PEM string or file path).
    • :verify - Verify peer certificates (default true for client, false for server).
    • :ca - CA certificate path.
    • :trusted-cert - Trust specific certificate (for self-signed).
    • :ciphers - Cipher suite string.
    • :security - Security options table.

If :cert and :key are provided, creates a server-capable context. Otherwise creates a client-only context.

Returns: SSLContext that can be passed to dtls/connect or dtls/listen.

Security Options

The :security option in connect and accept allows fine-grained control:

  • :min-version: Keyword or string. For TLS: :TLS1_2, :TLS1_3, or "TLS1.2", "TLS1.3". For DTLS: :DTLS1_0, :DTLS1_2, or "DTLS1.0", "DTLS1.2".
  • :max-version: Keyword or string. Same format as :min-version.
  • :ciphers: Keyword or string. OpenSSL cipher list format (e.g., :HIGH, "ECDHE-RSA-AES256-GCM-SHA384").
  • :curves: Keyword or string. Supported elliptic curves (e.g., :prime256v1, "prime256v1:secp384r1").
  • :ca-file: CA certificate (path or PEM content).
  • :ca-path: CA directory path.

Note: Keyword symbols are preferred for idiomatic Janet code.

Example: See policy_enforcement.janet for advanced security configuration.