mcrypt

package module
v1.0.0-rc.1 Latest Latest
Warning

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

Go to latest
Published: Jun 17, 2026 License: GPL-3.0 Imports: 8 Imported by: 0

README

mcrypt-go

Go Reference

A Go library for Rijndael-256 encryption and decryption, designed to provide full compatibility with PHP's legacy mcrypt extension (MCRYPT_RIJNDAEL_256).


Why does this library exist?

Go's standard crypto/aes package implements the FIPS 197 AES standard. Although AES is based on Rijndael, AES strictly limits the block size to 128 bits (16 bytes), regardless of key length.

However, PHP's legacy mcrypt extension allowed using Rijndael with a 256-bit block size (32 bytes) via the MCRYPT_RIJNDAEL_256 constant.

Standard Go does not support 256-bit blocks. Attempting to decrypt data encrypted with MCRYPT_RIJNDAEL_256 using crypto/aes will fail or produce corrupted output.

This library implements the Rijndael-256 block cipher natively in Go, conforming to the standard cipher.Block interface, with ECB and CBC modes that exactly match PHP's behavior (including NUL-byte padding).


Features

  • 100% PHP mcrypt compatibility: Encrypts and decrypts data identically to mcrypt_decrypt / mcrypt_encrypt with MCRYPT_RIJNDAEL_256.
  • All standard block cipher modes: ECB, CBC, CFB, OFB, and CTR with a 32-byte (256-bit) block size.
  • NUL-byte padding: Matches PHP mcrypt's default padding behavior.
  • Standard Go interface: Implements cipher.Block for interoperability with Go's crypto tooling.
  • URL-safe Base64: Handles URL-safe Base64 payloads (swapping -/_ for +//).
  • Cryptographically secure IV generation: GenerateIV() using crypto/rand.
  • Stream cipher wrapper: NewStreamWriter / NewStreamReader for chunk-based encryption of large data.
  • Sensitive memory clearing: ClearMem for timing-safe zeroing of sensitive data.
  • Specific error types: ErrInvalidIV, ErrInvalidKey, ErrInvalidNonce, ErrInvalidCiphertext, ErrEmptyPassword.

Installation

go get codeberg.org/simplicer/mcrypt-go

Usage

PHP mcrypt interoperability

If you're migrating a PHP API that encrypts credentials like this:

function decrypt($psw, $data){
    $data = str_replace(array('-','_'), array('+','/'), $data);
    $mod4 = strlen($data) % 4;
    if ($mod4) $data .= substr('====', $mod4);
    $decoded = base64_decode($data);
    return mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $psw, $decoded, MCRYPT_MODE_ECB);
}

The exact equivalent in Go:

package main

import (
	"fmt"
	"log"

	"codeberg.org/simplicer/mcrypt-go"
)

func main() {
	partnerPassword := "h3SdkVj2#!dkj3-D$5P"
	payload := "TQ3qLcs6FmgOBel-AAOhO97uE4SCRvj-uVbABOM_uNVF6k8JjwbLF1i7OFTfvedWGh9ZnMnW1PoKNmCKiYWT57kPmOVJC8Qi6K0wtKQxfbtenWCBv8ZricPjXXdJnvuPAvIRdDKO9wodxM_6OiSQp_8Dzku-3UMCRYo1cBCKv1Y"

	decrypted, err := mcrypt.DecryptPHP(partnerPassword, payload)
	if err != nil {
		log.Fatalf("decrypt error: %v", err)
	}

	fmt.Printf("Decrypted: %s\n", decrypted)
	// Output: {"password":"r3fZNZmHL2ra3h!","auth":"p79itgjfhbvou4df","admin":"ARB588SF-ITNIC","tech":"ARB5TECH-ITNIC"}

	encrypted, err := mcrypt.EncryptPHP(partnerPassword, decrypted)
	if err != nil {
		log.Fatalf("encrypt error: %v", err)
	}
	fmt.Printf("Encrypted: %s\n", encrypted)
}
CBC mode with IV
key := mcrypt.PadKey([]byte("my-secret-key"))
iv := make([]byte, mcrypt.BlockSize) // 32 bytes for Rijndael-256

ciphertext, err := mcrypt.EncryptCBC(key, plaintext, iv)
decrypted, err := mcrypt.DecryptCBC(key, ciphertext, iv)
result := mcrypt.UnpadNull(decrypted)
CFB mode
key := mcrypt.PadKey([]byte("my-secret-key"))
iv := make([]byte, mcrypt.BlockSize)
// Use GenerateIV() for cryptographically random IV
ciphertext, err := mcrypt.EncryptCFB(key, plaintext, iv)
decrypted, err := mcrypt.DecryptCFB(key, ciphertext, iv)
OFB mode
ciphertext, err := mcrypt.EncryptOFB(key, plaintext, iv)
decrypted, err := mcrypt.DecryptOFB(key, ciphertext, iv) // symmetric
CTR mode
nonce := make([]byte, mcrypt.BlockSize) // or use mcrypt.GenerateIV()
ciphertext, err := mcrypt.EncryptCTR(key, plaintext, nonce)
decrypted, err := mcrypt.DecryptCTR(key, ciphertext, nonce) // symmetric
Stream cipher (large data)
w := mcrypt.NewStreamWriter(key, mcrypt.CTR, nonce, os.Stdout)
defer w.Close()
io.Copy(w, largeFile)

r := mcrypt.NewStreamReader(key, mcrypt.CTR, nonce, encryptedFile)
io.Copy(os.Stdout, r)
Secure IV generation
iv, err := mcrypt.GenerateIV() // 32 bytes from crypto/rand
if err != nil {
    log.Fatal(err)
}
// Use iv with EncryptCBC/EncryptCFB/EncryptOFB — never reuse an IV
Memory clearing
mcrypt.ClearMem(sensitiveData) // zero memory timing-safely
Raw block cipher access

For advanced use cases where you need the raw Rijndael-256 block cipher:

block, err := mcrypt.NewCipher(key) // key must be 16, 24, or 32 bytes
if err != nil {
    log.Fatal(err)
}

// Use with any crypto/cipher mode that accepts cipher.Block.
// Remember the block size is always 32 bytes:
// cipher.NewCFBEncrypter(block, iv32bytes)

API reference

Function Description
EncryptPHP(password, plaintext) Encrypt to URL-safe Base64 (PHP compatible)
DecryptPHP(password, payload) Decrypt from URL-safe Base64 (PHP compatible)
EncryptECB(key, plaintext) Encrypt in ECB mode
DecryptECB(key, ciphertext) Decrypt in ECB mode
EncryptCBC(key, plaintext, iv) Encrypt in CBC mode
DecryptCBC(key, ciphertext, iv) Decrypt in CBC mode
EncryptCFB(key, plaintext, iv) Encrypt in CFB mode
DecryptCFB(key, ciphertext, iv) Decrypt in CFB mode
EncryptOFB(key, plaintext, iv) Encrypt in OFB mode
DecryptOFB(key, ciphertext, iv) Decrypt in OFB mode
EncryptCTR(key, plaintext, nonce) Encrypt in CTR mode
DecryptCTR(key, ciphertext, nonce) Decrypt in CTR mode
GenerateIV() Generate cryptographically secure random IV
NewStreamWriter(key, mode, iv, w) Stream encrypt large data to an io.Writer
NewStreamReader(key, mode, iv, r) Stream decrypt large data from an io.Reader
ClearMem(b) Zero memory timing-safely using crypto/subtle
PadKey(key) Pad key to 16/24/32 bytes with NUL
PadNull(data) Pad data to block boundary with NUL
UnpadNull(data) Strip trailing NUL bytes
NewCipher(key) Get raw cipher.Block for advanced use
Error types
Error When returned
ErrInvalidIV IV is not 32 bytes
ErrInvalidKey Key is not 16, 24, or 32 bytes
ErrInvalidNonce CTR nonce is not 32 bytes
ErrInvalidCiphertext Ciphertext length is not a multiple of 32
ErrEmptyPassword Partner password is empty

Testing

go test -v ./...

Versioning

This project follows Semantic Versioning with Conventional Commits. See CHANGELOG.md for details.


License

GNU General Public License v3.0 (GPL-3.0) — a strong copyleft license. Any application or library that uses or incorporates this package must be published and distributed under the same open-source terms. See LICENSE for details.


Author

Antonio Villamarin — antonio [at] simplicer [dot] com

Documentation

Index

Constants

View Source
const BlockSize = rijndael256.BlockSize

Variables

View Source
var ErrEmptyPassword = internal.ErrEmptyPassword
View Source
var ErrInvalidCiphertext = internal.ErrInvalidCiphertext
View Source
var ErrInvalidIV = internal.ErrInvalidIV
View Source
var ErrInvalidKey = internal.ErrInvalidKey
View Source
var ErrInvalidNonce = internal.ErrInvalidNonce

Functions

func ClearMem

func ClearMem(b []byte)

func DecryptCBC

func DecryptCBC(key, ciphertext, iv []byte) ([]byte, error)

func DecryptCFB

func DecryptCFB(key, ciphertext, iv []byte) ([]byte, error)

func DecryptCTR

func DecryptCTR(key, ciphertext, nonce []byte) ([]byte, error)

func DecryptECB

func DecryptECB(key, ciphertext []byte) ([]byte, error)

func DecryptOFB

func DecryptOFB(key, ciphertext, iv []byte) ([]byte, error)

func DecryptPHP

func DecryptPHP(partnerPassword, payload string) (string, error)

func EncryptCBC

func EncryptCBC(key, plaintext, iv []byte) ([]byte, error)

func EncryptCFB

func EncryptCFB(key, plaintext, iv []byte) ([]byte, error)

func EncryptCTR

func EncryptCTR(key, plaintext, nonce []byte) ([]byte, error)

func EncryptECB

func EncryptECB(key, plaintext []byte) ([]byte, error)

func EncryptOFB

func EncryptOFB(key, plaintext, iv []byte) ([]byte, error)

func EncryptPHP

func EncryptPHP(partnerPassword, plaintext string) (string, error)

func GenerateIV

func GenerateIV() ([]byte, error)

func NewCipher

func NewCipher(key []byte) (cipher.Block, error)

func NewStreamReader

func NewStreamReader(key []byte, mode Mode, iv []byte, r io.Reader) (io.Reader, error)

func NewStreamWriter

func NewStreamWriter(key []byte, mode Mode, iv []byte, w io.Writer) (io.WriteCloser, error)

func PadKey

func PadKey(key []byte) []byte

func PadNull

func PadNull(plaintext []byte) []byte

func UnpadNull

func UnpadNull(decrypted []byte) []byte

Types

type Mode

type Mode int
const (
	CBC Mode = iota
	CFB
	OFB
	CTR
)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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