Serpent128Cipher Class
Definition
- Namespace
- Bodu.Security.Cryptography
- Assembly
- Bodu.Security.Cryptography.dll
- Package
- Bodu.Security.Cryptography 1.2.0
- Source
- Serpent128Cipher.cs
Implements the canonical Serpent block cipher, which operates on 128-bit (16-byte) blocks using a 128, 192,
or 256-bit key.
public sealed class Serpent128Cipher : SerpentBlockCipherBase, IBlockCipher, IDisposable
- Inheritance
-
Serpent128Cipher
- Implements
- Inherited Members
- Extension Methods
Examples
// Direct single-block use. For most workloads prefer the Serpent128 SymmetricAlgorithm wrapper.
byte[] key = new byte[32]; // 128, 192, or 256 bits - Serpent pads shorter keys to 256
RandomNumberGenerator.Fill(key);
using var cipher = new Serpent128Cipher(key);
byte[] plaintext = new byte[16]; // one 128-bit block
byte[] ciphertext = new byte[16];
cipher.Encrypt(plaintext, ciphertext);
byte[] roundtrip = new byte[16];
cipher.Decrypt(ciphertext, roundtrip);
// roundtrip equals plaintext
Remarks
Serpent is a 32-round substitution-permutation network designed by Ross Anderson, Eli Biham, and Lars Knudsen as an
Advanced Encryption Standard (AES) candidate. Each round applies a round-key XOR, one of the eight 4-bit S-boxes
S0..S7, and the bitsliced linear transformation L. The final round replaces L with a post-round
key XOR. Shorter keys are padded to 256 bits by appending a 1 bit followed by zeros, per the Serpent
specification.
This class implements the standard Serpent-128 block primitive only. It is interoperable with canonical Serpent test vectors and does not use the tweak schedule or widened state used by the non-standard wide-block variants.
Most callers should prefer the higher-level Serpent128 class, which exposes the standard SymmetricAlgorithm contract. Use Serpent128Cipher directly only when composing the raw block primitive with an IBlockCipherModeTransform or IPaddingStrategy.
This implementation computes each S-box as a Boolean circuit (Osvik's) and the linear transform with rotations, shifts and XOR, so it reads no tables and takes no branches that depend on the key or the data: its running time does not depend on either.
Constructors
Serpent128Cipher(ReadOnlySpan<byte>)
Initializes a new instance of the Serpent128Cipher class using the specified key.
public Serpent128Cipher(ReadOnlySpan<byte> key)
Parameters
keyReadOnlySpan<byte>The Serpent key. Length must be 16, 24, or 32 bytes (128, 192, or 256 bits). Shorter keys are padded to 256 bits per the Serpent specification.
Exceptions
- ArgumentException
keydoes not have a length of 16, 24, or 32 bytes.
Properties
BlockSize
Gets the block size, in bits, of the cipher (for example, 128 bits / 16 bytes for AES).
public override int BlockSize { get; }
Property Value
- int
The block size, in bits.
Remarks
The block size is expressed in bits to align with the BCL convention used by
BlockSize. Byte-array operations (encrypt,
decrypt, slice) convert to bytes at the call site as BlockSize / 8.
Methods
Decrypt(ReadOnlySpan<byte>, Span<byte>)
Decrypts a single block of ciphertext into the specified output span.
public override void Decrypt(ReadOnlySpan<byte> input, Span<byte> output)
Parameters
inputReadOnlySpan<byte>A read-only span containing the ciphertext block. Its byte length must equal BlockSize / 8.
outputSpan<byte>A writable span that receives the plaintext block. Its byte length must equal BlockSize / 8.
Remarks
In-place decryption (passing the same buffer as both input and output)
is supported only when the implementation explicitly permits it; otherwise the spans must not overlap.
Exceptions
- ArgumentException
Thrown if the length of
inputoroutputdoes not match BlockSize.
Dispose(bool)
Releases all internal buffers and sensitive material.
protected override void Dispose(bool disposing)
Parameters
Remarks
The base implementation records the disposed state. Derived Serpent implementations should override this method
to clear expanded round keys, tweak material, and other sensitive buffers before calling
base.Dispose(disposing).
Encrypt(ReadOnlySpan<byte>, Span<byte>)
Encrypts a single block of plaintext into the specified output span.
public override void Encrypt(ReadOnlySpan<byte> input, Span<byte> output)
Parameters
inputReadOnlySpan<byte>A read-only span containing the plaintext block. Its byte length must equal BlockSize / 8.
outputSpan<byte>A writable span that receives the ciphertext block. Its byte length must equal BlockSize / 8.
Remarks
In-place encryption (passing the same buffer as both input and output)
is supported only when the implementation explicitly permits it; otherwise the spans must not overlap.
Exceptions
- ArgumentException
Thrown if the length of
inputoroutputdoes not match BlockSize.
Explicit Interface Implementations
IBlockCipher.DecryptBlocks(ReadOnlySpan<byte>, Span<byte>)
Decrypts a run of one or more contiguous blocks, each independently (ECB semantics), writing the plaintext into
output.
void IBlockCipher.DecryptBlocks(ReadOnlySpan<byte> input, Span<byte> output)
Parameters
inputReadOnlySpan<byte>The ciphertext blocks. Length must be a positive multiple of BlockSize / 8.
outputSpan<byte>The destination for the plaintext. Must be at least
input.Length bytes.
Remarks
The default implementation calls Decrypt(ReadOnlySpan<byte>, Span<byte>) once per block; see EncryptBlocks(ReadOnlySpan<byte>, Span<byte>) for when to override.
Exceptions
- ObjectDisposedException
The instance has been disposed.
- ArgumentException
inputis not a whole number of blocks, oroutputis shorter thaninput.
IBlockCipher.EncryptBlocks(ReadOnlySpan<byte>, Span<byte>)
Encrypts a run of one or more contiguous blocks, each independently (ECB semantics), writing the ciphertext into
output.
void IBlockCipher.EncryptBlocks(ReadOnlySpan<byte> input, Span<byte> output)
Parameters
inputReadOnlySpan<byte>The plaintext blocks. Length must be a positive multiple of BlockSize / 8.
outputSpan<byte>The destination for the ciphertext. Must be at least
input.Length bytes.
Remarks
The default implementation calls Encrypt(ReadOnlySpan<byte>, Span<byte>) once per block. Implementations backed by a primitive with per-call setup cost (for example a wrapped BCL cipher context) should override this to amortize that cost across the whole run. Callers that process independent blocks - ECB and the keystream layer of CTR-based modes - should prefer this over a per-block loop.
Exceptions
- ObjectDisposedException
The instance has been disposed.
- ArgumentException
inputis not a whole number of blocks, oroutputis shorter thaninput.
Applies to
| Product | Versions |
|---|---|
| .NET | 8, 10 |