serpent

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Nov 10, 2026 License: BSD-3-Clause Imports: 4 Imported by: 0

README

go-encryptions/serpent

go-encryptions/serpent

ci Go Reference

Pure-Go Serpent block cipher (Anderson, Biham and Knudsen, AES finalist) as a standard crypto/cipher.Block: 16-byte blocks, 16-, 24- or 32-byte keys. Bitsliced, no cgo, no dependency outside the standard library.

Its first consumer is go-fde/veracrypt, which needs Serpent in XTS mode with 256-bit keys (via go-encryptions/xts) to open VeraCrypt volumes.

Install

go get github.com/go-encryptions/serpent

Usage

import "github.com/go-encryptions/serpent"

block, err := serpent.NewCipher(key) // 16, 24 or 32 bytes
if err != nil {
	// a serpent.KeySizeError for any other length
}
block.Encrypt(dst[:16], src[:16]) // dst and src may be the same slice
block.Decrypt(dst[:16], src[:16]) // a buffer under 16 bytes panics

The contract is that of cipher.Block: in-place operation is allowed and short buffers panic. serpent.BlockSize is 16.

Byte order

Serpent has two byte-order conventions. This package uses the standard one, that of Botan, VeraCrypt and the Linux serpent algorithm: the key and the block are read as little-endian 32-bit words. The reversed order (Linux tnepres, and the original submission's test files) is not provided.

The vectors in testdata/botan-serpent.vec are Botan's src/tests/data/block/serpent.vec, produced with Botan's standard order, and all 1047 pass, so they confirm that order. I did not obtain the NESSIE vector files, so no NESSIE vector is claimed.

Verification

  • testdata/botan-serpent.vec: Botan's own Serpent vectors, 1047 keys (261 at 128 bits, 327 at 192, 459 at 256), each over one or more blocks, encrypted and decrypted.
  • testdata/botan-diff.vec: a differential corpus of 750 random keys and blocks (250 per key size, plus all-zero and all-one keys) generated from the Botan 3.14.1 command line by internal/genbotan (go run ./internal/genbotan). Regenerating needs botan on the PATH.
  • FuzzRoundTrip cross-checks Encrypt and Decrypt round trips on every key length and the refusal of other lengths; CI runs it for 60 seconds, and its corpus is in testdata/fuzz.
  • CI: race detector and a 100 % statement-coverage gate on amd64 and arm64; the same tests under QEMU on big-endian s390x and on riscv64; govulncheck.

Implementation

The S-box expressions are Dag Arne Osvik's bitsliced forms as used by Botan's serpent_sbox.h (BSD-2-Clause); the structure of the rounds and of the key schedule follows Botan's serpent.cpp. The linear transformation, the round structure, the key schedule (golden-ratio constant 0x9e3779b9, a short key padded with a single 1 bit, prekeys turned into round keys by the S-boxes in bitslice mode) are those of sections 3 and 4 of the Serpent submission. Linux's GPL serpent_generic.c was not used.

Bibliography opened for this work: the Serpent AES submission (serpent.pdf, sections 3 and 4, the page); Botan serpent.cpp, serpent_sbox.h and serpent.vec.

Performance

BenchmarkEncrypt and BenchmarkDecrypt loop the block over a 4 KiB buffer, the shape of one XTS sector, with no allocation. The reference is Botan 3.14.1 (botan speed --buf-size=4096 Serpent, wrapped as Go benchmarks by internal/botanbench so that abbench can interleave it). Apple M4 Max (arm64), one core (GOMAXPROCS=1), 6 interleaved rounds by abbench --max-load 8 (2 rounds discarded for load, per run), compared with benchstat; every result file holds 12 ^Benchmark lines.

4 KiB, per call this package Botan, NEON (default) Botan, scalar (--clear-cpuid=neon)
Encrypt 32.75 µs (119 MiB/s) 15.92 µs (245 MiB/s), 2.1x faster 30.76 µs ± 39 %, 1.06x faster
Decrypt 29.93 µs (131 MiB/s) 12.15 µs (321 MiB/s), 2.5x faster 26.87 µs ± 76 %, 1.11x faster

Times are per 4 KiB call, so lower is better; the "faster" figures are Botan's advantage. The scalar column was measured while the machine's load kept moving, and its spread is wide (± 39 % and ± 76 %): read it as "same order as this package", not as a precise ratio. Botan's default build uses NEON bitslicing over several blocks at once; this package runs one block at a time in scalar Go, so it is slower than the reference. The SIMD follow-up is issue #2.

Reproduce: go test -c -o serpent.test ., go test -c -o botan.test ./internal/botanbench, then abbench --base ./serpent.test --head ./botan.test --max-load 8 -n 6 -- -test.bench . -test.run '^$' (add --head-arg=-botan.clear-cpuid=neon for the scalar column).

License

BSD-3-Clause © the go-encryptions/serpent authors.

Documentation

Overview

Package serpent implements the Serpent block cipher (Anderson, Biham and Knudsen, AES candidate) as a crypto/cipher.Block.

The byte order is the standard one used by Botan, VeraCrypt and the Linux "serpent" algorithm: the 16-byte block and the key are read as little-endian 32-bit words. It is NOT the reversed order of Linux's "tnepres" nor of the original submission's test files.

The implementation is bitsliced, one block at a time, in pure Go.

Index

Constants

View Source
const BlockSize = 16

BlockSize is the Serpent block size in bytes.

Variables

This section is empty.

Functions

func NewCipher

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

NewCipher returns a Serpent cipher.Block for a 16, 24 or 32 byte key. Other lengths return a KeySizeError.

Types

type KeySizeError

type KeySizeError int

KeySizeError is returned by NewCipher for a key length other than 16, 24 or 32 bytes.

func (KeySizeError) Error

func (k KeySizeError) Error() string

Directories

Path Synopsis
internal
genbotan command
Command genbotan writes testdata/botan-diff.vec, a differential corpus of Serpent single-block vectors produced by the installed Botan command line (`botan cipher --cipher=Serpent/CBC/NoPadding` with a zero IV, which on one block is plain ECB).
Command genbotan writes testdata/botan-diff.vec, a differential corpus of Serpent single-block vectors produced by the installed Botan command line (`botan cipher --cipher=Serpent/CBC/NoPadding` with a zero IV, which on one block is plain ECB).

Jump to

Keyboard shortcuts

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