npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

sentence-cipher

v2.1.0

Published

A Go/Node.js library that encodes data into natural-looking English sentences for steganography.

Readme

Sentence Cipher

A multi-language library (Go & TypeScript) that encodes arbitrary binary data into natural-looking English sentences. Hide your secret messages in plain sight!

Sentence Cipher Modes

Overview

Sentence Cipher transforms any byte sequence into grammatically correct English sentences using a workplace/office theme vocabulary. Unlike simple substitution ciphers, it constructs meaningful sentence structures that mimic professional communication.

Example

Mode: String
Input:  "Hello"
Output: "ruth trains isabella prints. carl cleans daily."
Mode: Natural
Input:  "Hello"
Output:
"""
Subject: Code Review

Hi Team,

Ian imports sandra os. Specifically, Leo sorts daily. 

Best regards,
Samantha
"""
Mode: Binary
Input:  "Hello"
Output: "ruth trains isabella prints. carl cleans daily."

How It Works

The library offers three primary modes of operation to suit different needs:

📝 String Mode

Standard encoding that transforms text into office-themed sentences. It handles UTF-8 strings directly, making it perfect for short text messages or chat applications.

📧 Natural Mode

Advanced encoding that structures data into a natural-looking email format. It wraps the encoded sentences with realistic:

  • Subjects: "Code Review", "Meeting Notes", "Project Update"
  • Openers: "Hi Team,", "Good morning,"
  • Connectors: "Specifically,", "Additionally,"
  • Closers: "Best regards,", "Cheers,"

This mode generates output that looks indistinguishable from a real workplace email, providing better cover for your data.

💾 Binary Mode

Raw byte encoding for any file type (images, documents, executables). It maintains data integrity by treating the input as a raw byte stream. The output looks the same as String Mode but ensures that binary data is perfectly preserved during the round-trip.


Encoding Scheme

The cipher uses three word lists, each containing exactly 256 words (mapping to byte values 0-255):

| Word List | Purpose | Examples | |-----------|---------|----------| | Names | Subjects & Indirect Objects | adam, alex, alice... | | Verbs | Actions | helps, assists, supports... | | Objects | Direct Objects | reports, documents, files... |

Sentence Patterns

Data is encoded using three different sentence patterns depending on the remaining bytes:

  1. Full Sentence (3 bytes): [Subject] [Verb] [IndirectObject] [Object].
  2. Short Sentence (2 bytes): [Subject] [Verb] daily.
  3. Minimal Sentence (1 byte): [Subject] works.

Installation

Go

go get github.com/kittizz/sentence-cipher

Node.js / TypeScript

npm install sentence-cipher
# or
pnpm add sentence-cipher

Usage

Go Library

package main

import (
    "fmt"
    sentencecipher "github.com/kittizz/sentence-cipher"
)

func main() {
    // 1. Basic encoding/decoding
    message := "Hello World"
    encoded := sentencecipher.EncodeString(message)
    fmt.Println(encoded) 
    // Output: "ruth trains isabella prints. carl cleans daily..."

    // 2. Natural Mode (Email style)
    naturalEncoded := sentencecipher.EncodeNatural([]byte(message))
    fmt.Println(naturalEncoded)
    // Output: "Subject: Project Update\nHi Team,\nRuth trains..."

    // 3. With Encryption Key
    cipher := sentencecipher.NewCipher("my-secret-key")
    secureEncoded := cipher.EncodeString(message)
    
    // Decode
    decoded, _ := cipher.DecodeString(secureEncoded)
    fmt.Println(decoded)
}

Node.js / TypeScript Library

The JavaScript library provides a Type-Safe API with full support for all modes.

import { createCipher, createDefaultCipher } from 'sentence-cipher';

// Initialize
const cipher = createDefaultCipher();

// --- String Mode ---
const encoded = cipher.encodeString("Hello World");
const decoded = cipher.decodeString(encoded);
console.log(encoded); 
// "ruth trains isabella prints. carl cleans daily."


// --- Natural Mode ---
// Natural mode works with Uint8Array to support any data
const input = new TextEncoder().encode("Hello World");
const naturalEncoded = cipher.encodeNatural(input);

console.log(naturalEncoded);
/*
Subject: Team Sync
Hi Everyone,
Ruth trains isabella prints. Carl cleans daily.
Best,
*/

const naturalDecoded = cipher.decodeNatural(naturalEncoded);
console.log(new TextDecoder().decode(naturalDecoded)); // "Hello World"


// --- Binary Mode ---
// Perfect for files or raw data
const data = new Uint8Array([72, 101, 108, 108, 111]); // "Hello" bytes
const binaryEncoded = cipher.encode(data);
const binaryDecoded = cipher.decode(binaryEncoded);


// --- Encryption Key ---
// Provide a key to shuffle the word lists deterministically
const secureCipher = createCipher("my-super-secret-key");
const secureMsg = secureCipher.encodeString("Secret Data");

// Must use the same key to decode
const decryptedMsg = secureCipher.decodeString(secureMsg);

Command Line Tool (CLI)

You can also use the Go CLI to encode/decode files or text from the terminal.

# Install
go install github.com/kittizz/sentence-cipher/cmd/sentencecipher@latest

# Usage
sentencecipher "Hello World"
sentencecipher -d "ruth trains isabella prints..."
sentencecipher -n "Generate natural email"
sentencecipher -k "my-key" "Encrypted message"

Technical Details

Key Derivation & Security

When a key is provided, the library uses SHA-256 to hash the key. The hash is used to seed a Fisher-Yates shuffle algorithm, which randomizes the order of the Names, Verbs, and Objects word lists. This ensures that without the correct key, the sentence mapping is completely different, effectively encrypting the message.

Expansion Ratio

The encoding transforms binary data into English text, which naturally increases the size.

  • Expansion: Approximately 15-20x original size.
  • Efficiency:
    • 3 bytes → ~4 words
    • 2 bytes → ~3 words
    • 1 byte → ~2 words

License

MIT License