denygo

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 11, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

README

deny-go

Go SDK for deny.sh — deniable encryption that lies for you.

Algorithm-compatible with the TypeScript and Python SDKs. Ciphertext produced by any SDK can be decrypted by any other.

Install

go get github.com/deny-sh-crypto/deny-go

Requires Go 1.21+.

Usage

package main

import (
	"fmt"
	denysh "github.com/deny-sh-crypto/deny-go"
)

func main() {
	// Encrypt (control data auto-generated when nil)
	ct, ctrl, _ := denysh.Encrypt([]byte("seed phrase"), "pw1", "pw2", nil)

	// Decrypt with real control data → real message
	msg, _ := denysh.Decrypt(ct, "pw1", "pw2", ctrl)
	fmt.Println(string(msg)) // "seed phrase"

	// Generate deniable control data → same ciphertext decrypts to decoy
	fakeCtrl, _ := denysh.GenerateDeniableControl(ct, "pw1", "pw2", []byte("decoy seed"))
	decoy, _ := denysh.Decrypt(ct, "pw1", "pw2", fakeCtrl)
	fmt.Println(string(decoy)) // "decoy seed"
}

API

Encrypt(plaintext []byte, password1, password2 string, controlData []byte) (ciphertext, control []byte, err error)

Encrypts plaintext using dual passwords and a control file. If controlData is nil, random control data is generated automatically.

Decrypt(ciphertext []byte, password1, password2 string, controlData []byte) (plaintext []byte, err error)

Decrypts ciphertext using dual passwords and the control data.

GenerateDeniableControl(ciphertext []byte, password1, password2 string, desiredPlaintext []byte) (controlData []byte, err error)

Generates new control data that makes existing ciphertext decrypt to a different plaintext.

GenerateControlData(size int) []byte

Generates cryptographically secure random control data.

DeriveKey(password1, password2 string, salt []byte) []byte

Derives an AES-256 key from two passwords and a salt using scrypt (N=16384, r=8, p=1).

Algorithm

  • KDF: scrypt (N=16384, r=8, p=1, keylen=32) on SHA-256(pw1) || SHA-256(pw2)
  • Cipher: AES-256-CTR
  • Deniability: XOR with control data, 4-byte LE length prefix inside encrypted zone
  • Format: salt(32) + iv(16) + AES-CTR(payload ⊕ control_data)

Tests

go test -v ./...

25 tests covering roundtrips, deniability, KAT vectors, unicode, edge cases.

License

Apache License 2.0. See LICENSE. Free for commercial and proprietary use. See deny.sh/licensing.

Documentation

Overview

Package denygo implements the deny.sh deniable encryption algorithm.

Algorithm-compatible with the TypeScript and Python reference implementations. Ciphertext produced by any SDK can be decrypted by any other.

Algorithm:

ENCRYPT:

  1. Derive AES-256 key from password1 + password2 via scrypt
  2. Prepend 4-byte LE plaintext length to plaintext (inside encrypted zone)
  3. XOR (length + plaintext) with control data
  4. AES-256-CTR encrypt the result
  5. Prepend: salt (32 bytes) + IV (16 bytes) as unencrypted header

DECRYPT:

  1. Extract salt + IV from header
  2. Re-derive AES-256 key from passwords + salt
  3. AES-256-CTR decrypt payload
  4. XOR with control data
  5. Read 4-byte length prefix, trim plaintext to that length

DENIABLE DECRYPTION:

Given ciphertext + passwords + desired fake plaintext:
1. AES decrypt to get intermediate (= length+plaintext XOR controlData)
2. Construct fake payload = 4-byte-length(fake) + fake plaintext + random padding
3. New control data = intermediate XOR fake payload
4. Now decrypting with new control file produces the fake plaintext

Index

Constants

View Source
const (
	SaltLength   = 32
	IVLength     = 16
	KeyLength    = 32                    // AES-256
	HeaderLength = SaltLength + IVLength // 48 bytes
	LengthPrefix = 4                     // 4-byte LE length prefix

)

Constants matching the TypeScript/Python reference implementations.

Variables

This section is empty.

Functions

func Decrypt

func Decrypt(ciphertext []byte, password1, password2 string, controlData []byte) ([]byte, error)

Decrypt decrypts ciphertext using dual passwords and the control data.

func DeriveKey

func DeriveKey(password1, password2 string, salt []byte) []byte

DeriveKey derives an AES-256 key from two passwords and a salt using scrypt. Combines both passwords via SHA-256 hashing to avoid length ambiguities.

func Encrypt

func Encrypt(plaintext []byte, password1, password2 string, controlData []byte) ([]byte, []byte, error)

Encrypt encrypts plaintext using dual passwords and control data.

If controlData is nil, random control data is generated automatically. Returns (ciphertext, controlData, error). Ciphertext format: salt(32) + iv(16) + AES-256-CTR(payload XOR controlData).

func GenerateControlData

func GenerateControlData(size int) []byte

GenerateControlData generates cryptographically secure random control data.

func GenerateDeniableControl

func GenerateDeniableControl(ciphertext []byte, password1, password2 string, desiredPlaintext []byte) ([]byte, error)

GenerateDeniableControl generates new control data that makes existing ciphertext decrypt to a completely different plaintext.

Given:

  • Original ciphertext (encrypted with password1 + password2 + originalControlData)
  • The same passwords
  • A desired fake plaintext

Returns new control data such that Decrypt(ciphertext, pw1, pw2, newControl) = desiredPlaintext.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL