Thanks to visit codestin.com
Credit goes to GitHub.com

Skip to content

isolomak/bencodec

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

160 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

bencodec

CI Coverage Status npm version npm downloads License: MIT TypeScript Zero Dependencies

A fast, secure, zero-dependency bencode encoder/decoder for modern JavaScript runtimes.

Universal TypeScript library compliant with the BitTorrent bencoding specification. Works in Node.js, browsers, Deno, and Bun.

Highlights

  • Zero Dependencies - No external packages, minimal attack surface
  • Universal - Works in Node.js, browsers, Deno, and Bun
  • TypeScript First - Full type definitions with generics support
  • Security Built-in - DoS protection with configurable limits
  • BitTorrent Compliant - Strict mode for spec validation
  • Modern API - Uses Uint8Array (not Node.js Buffer)
  • Dual Package - ESM and CommonJS exports
  • 100% Tested - Complete code coverage

Installation

# npm
npm install bencodec

# yarn
yarn add bencodec

# pnpm
pnpm add bencodec

# bun
bun add bencodec

Quick Start

import { encodeToBytes, encodeToString, decode } from 'bencodec';

// Encode JavaScript values to bencode (Uint8Array)
const bytes = encodeToBytes({ announce: 'http://tracker.example.com', info: { name: 'file.txt' } });

// Encode JavaScript values to bencode (string)
const str = encodeToString({ announce: 'http://tracker.example.com', info: { name: 'file.txt' } });

// Decode bencode data
const decoded = decode(bytes, { stringify: true });
// { announce: 'http://tracker.example.com', info: { name: 'file.txt' } }

Usage

Decoding

import { decode } from 'bencodec';

// Decode integers
decode('i42e');  // 42

// Decode strings (returns Uint8Array by default)
decode('5:hello');  // Uint8Array [0x68, 0x65, 0x6c, 0x6c, 0x6f]

// Decode strings as JavaScript strings
decode('5:hello', { stringify: true });  // 'hello'

// Decode lists
decode('li1ei2ei3ee', { stringify: true });  // [1, 2, 3]

// Decode dictionaries
decode('d3:fooi42e3:bar4:spame', { stringify: true });  // { bar: 'spam', foo: 42 }

// Type the result with generics
interface Torrent {
  announce: string;
  info: { name: string };
}
const torrent = decode<Torrent>(buffer, { stringify: true });

Encoding

Encode to Bytes (Uint8Array)

import { encodeToBytes } from 'bencodec';

// Encode integers
encodeToBytes(42);  // Uint8Array for 'i42e'

// Encode strings
encodeToBytes('hello');  // Uint8Array for '5:hello'

// Encode lists
encodeToBytes([1, 2, 3]);  // Uint8Array for 'li1ei2ei3ee'

// Encode dictionaries (keys auto-sorted per spec)
encodeToBytes({ z: 1, a: 2 });  // Uint8Array for 'd1:ai2e1:zi1ee'

// Encode binary data
encodeToBytes(new Uint8Array([0x00, 0xff]));

Encode to String

import { encodeToString } from 'bencodec';

// Encode to string (UTF-8 by default)
encodeToString({ foo: 'bar' });  // 'd3:foo3:bare'

// Encode integers
encodeToString(42);  // 'i42e'

// Use latin1 encoding for binary data preservation
encodeToString(new Uint8Array([0x00, 0xff]), { encoding: 'latin1' });  // '2:\x00\xff'

// Supported encodings: 'utf8', 'utf-8', 'latin1', 'binary', 'ascii'
encodeToString({ foo: 42 }, { encoding: 'utf8' });

Legacy encode() (Deprecated)

import { encode } from 'bencodec';

// Deprecated - use encodeToBytes or encodeToString instead
encode(42);                        // Returns Uint8Array
encode({ foo: 'bar' }, { stringify: true });  // Returns string

Default Export

import bencodec from 'bencodec';

bencodec.encodeToBytes({ foo: 42 });
bencodec.encodeToString({ foo: 42 });
bencodec.decode('d3:fooi42ee');

Options

Decode Options (IBencodecOptions)

interface IBencodecOptions {
  /** Return strings instead of Uint8Array (default: false) */
  stringify?: boolean;

  /** Enable strict BitTorrent spec validation (default: false) */
  strict?: boolean;

  /** Character encoding: 'utf8' | 'latin1' | 'ascii' | 'binary' (default: 'utf8') */
  encoding?: ByteEncoding;

  /** Maximum string length in bytes - security limit */
  maxStringLength?: number;

  /** Maximum nesting depth - security limit */
  maxDepth?: number;
}

Encode to String Options (IBencodeEncodeOptions)

interface IBencodeEncodeOptions {
  /** Character encoding for output (default: 'utf8') */
  encoding?: 'utf8' | 'utf-8' | 'latin1' | 'binary' | 'ascii';
}

Strict Mode

Enable strict mode for BitTorrent specification compliance:

// Enforces sorted dictionary keys
decode('d1:bi1e1:ai2ee', { strict: true });
// Throws: UNSORTED_KEYS

// Rejects trailing data
decode('i42eextra', { strict: true });
// Throws: TRAILING_DATA

Security

Bencodec includes built-in protections against denial-of-service attacks when parsing untrusted data.

Memory Exhaustion Protection

Prevent memory exhaustion from maliciously large strings:

decode(untrustedData, {
  maxStringLength: 10 * 1024 * 1024  // 10 MB limit
});

Stack Overflow Protection

Prevent stack overflow from deeply nested structures:

decode(untrustedData, {
  maxDepth: 100  // Maximum nesting depth
});

Recommended Settings for Untrusted Data

const SAFE_OPTIONS = {
  maxStringLength: 10 * 1024 * 1024,  // 10 MB
  maxDepth: 100,
  strict: true
};

decode(untrustedData, SAFE_OPTIONS);

Error Handling

Bencodec provides structured error classes with specific error codes for programmatic handling.

Error Classes

import {
  BencodeError,        // Base class
  BencodeDecodeError,  // Decode errors (includes position)
  BencodeEncodeError,  // Encode errors (includes path)
  BencodeErrorCode
} from 'bencodec';

Error Codes

Code Description
EMPTY_INPUT Input data is empty or falsy
UNEXPECTED_END Data ends unexpectedly
INVALID_FORMAT Invalid bencode format
LEADING_ZEROS Integer has leading zeros (e.g., i03e)
NEGATIVE_ZERO Negative zero (i-0e) is not allowed
UNSORTED_KEYS Dictionary keys not sorted (strict mode)
TRAILING_DATA Extra data after valid bencode (strict mode)
MAX_DEPTH_EXCEEDED Nesting depth exceeds limit
MAX_SIZE_EXCEEDED String length exceeds limit
UNSUPPORTED_TYPE Attempted to encode unsupported type
CIRCULAR_REFERENCE Circular reference detected

Decode Error Example

import { decode, BencodeDecodeError, BencodeErrorCode } from 'bencodec';

try {
  decode(untrustedData, { strict: true, maxDepth: 50 });
} catch (error) {
  if (error instanceof BencodeDecodeError) {
    switch (error.code) {
      case BencodeErrorCode.MAX_DEPTH_EXCEEDED:
        console.error(`Too deeply nested at position ${error.position}`);
        break;
      case BencodeErrorCode.INVALID_FORMAT:
        console.error(`Malformed data at position ${error.position}`);
        break;
    }
  }
}

Encode Error Example

import { encode, BencodeEncodeError } from 'bencodec';

try {
  const circular: any = { a: 1 };
  circular.self = circular;
  encode(circular);
} catch (error) {
  if (error instanceof BencodeEncodeError) {
    console.error(`Error at path: ${error.path?.join('.')}`);
    // Output: Error at path: self
  }
}

Platform Support

Platform Version Notes
Node.js 18+ Full support
Browsers Modern Chrome, Firefox, Safari, Edge
Deno 1.0+ Full support
Bun 1.0+ Full support

Browser Usage

<script type="module">
  import { encode, decode } from 'https://esm.sh/bencodec';

  const encoded = encode({ hello: 'world' });
  console.log(decode(encoded, { stringify: true }));
</script>

Deno Usage

import { encode, decode } from 'npm:bencodec';

const encoded = encode({ hello: 'world' });
console.log(decode(encoded, { stringify: true }));

Type Definitions

Full TypeScript support with exported types:

import type {
  IBencodecOptions,
  IBencodeEncodeOptions,
  BencodeDecodedValue,
  BencodeEncodableValue,
  ByteEncoding
} from 'bencodec';

Non-Standard Behaviors

For maximum compatibility, bencodec handles some edge cases beyond the strict spec:

Behavior Description
Plus sign in integers Leading + is silently ignored (i+42e -> 42)
Float truncation Decimal numbers truncated toward zero
Boolean encoding Booleans encoded as integers (true -> i1e)
Null/undefined Silently skipped in lists and dictionaries

License

MIT

About

Library for decoding and encoding bencoded data.

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •