SpeckEx

A high-performance Elixir library for the Speck block cipher, powered by Rust NIFs. Provides both low-level block cipher primitives and high-level CTR mode encryption.

Note that the backing Rust crate is a prerelease version at this time.

License

Features

Supported Variants

Variant Block Size Key Size CTR Mode Support
speck32_64 32-bit (4 bytes) 64-bit (8 bytes) βœ…
speck48_72 48-bit (6 bytes) 72-bit (9 bytes) ❌
speck48_96 48-bit (6 bytes) 96-bit (12 bytes) ❌
speck64_96 64-bit (8 bytes) 96-bit (12 bytes) βœ…
speck64_128 64-bit (8 bytes) 128-bit (16 bytes) βœ…
speck96_96 96-bit (12 bytes) 96-bit (12 bytes) ❌
speck96_144 96-bit (12 bytes) 144-bit (18 bytes) ❌
speck128_128 128-bit (16 bytes) 128-bit (16 bytes) βœ…
speck128_192 128-bit (16 bytes) 192-bit (24 bytes) βœ…
speck128_256 128-bit (16 bytes) 256-bit (32 bytes) βœ… (default)

Note: CTR mode is only available for variants with standard block sizes (32, 64, 128 bits) due to Rust ctr crate limitations. All variants support low-level block operations.

Installation

Add speck_ex to your list of dependencies in mix.exs:

def deps do
  [
    {:speck_ex, "~> 0.1.0"}
  ]
end

Requirements

Precompiled Binaries: SpeckEx includes precompiled NIFs for most common architectures (Linux, macOS, Windows on x86_64, ARM64, etc.). The Rust toolchain is not required for typical installations.

If you’re on an unsupported platform, Rustler will automatically compile from source during installation, which requires the Rust toolchain.

Quick Start

High-Level CTR Mode Encryption

# Generate a random key and iv
key = :crypto.strong_rand_bytes(32)    # 256-bit key
iv = :crypto.strong_rand_bytes(16)  # 128-bit iv

# Encrypt data
plaintext = "Hello, World! This is a secret message."
ciphertext = SpeckEx.encrypt(plaintext, key, iv)

# Decrypt data
decrypted = SpeckEx.decrypt(ciphertext, key, iv)
# => "Hello, World! This is a secret message."

Using Different Variants

# Speck128/128 (smaller key)
key = :crypto.strong_rand_bytes(16)
iv = :crypto.strong_rand_bytes(16)
ciphertext = SpeckEx.encrypt("Secret data", key, iv, variant: :speck128_128)

# Speck64/128 (smaller block size)
key = :crypto.strong_rand_bytes(16)
iv = :crypto.strong_rand_bytes(8)   # 64-bit iv
ciphertext = SpeckEx.encrypt("Secret data", key, iv, variant: :speck64_128)

Low-Level Block Operations

These low-level operations apply the cipher to single data blocks. These operations can be used to implement different block modes (although that could probably be done in a more performant way in Rust). You will probably not want to use these operations directly.

# Initialize cipher
key = :crypto.strong_rand_bytes(16)
cipher = SpeckEx.Block.speck128_128_init!(key)

# Encrypt a single 16-byte block
plaintext_block = :crypto.strong_rand_bytes(16)
ciphertext_block = SpeckEx.Block.speck128_128_encrypt!(plaintext_block, cipher)

# Decrypt the block
decrypted_block = SpeckEx.Block.speck128_128_decrypt!(ciphertext_block, cipher)

Security Considerations

⚠️ Important Security Notes:

  1. Never Reuse IVs: Each encryption with the same key MUST use a unique iv. IV reuse completely breaks CTR mode security.

  2. Use Cryptographically Secure Random: Always use :crypto.strong_rand_bytes/1 for generating keys and ivs.

  3. Speck Cipher Status: Speck is an NSA-designed cipher optimized for performance on constrained devices. While no practical attacks are known, it has received less academic scrutiny than AES. Consider your threat model carefully - the authors themselves recommend AES whenever the available compute resources allow it.

  4. No Authentication: This library provides encryption only. For authenticated encryption, combine with HMAC or use a higher-level AEAD construction.

  5. Side-Channel Attacks: The Rust implementation uses constant-time operations where possible, but has not been audited for side-channel resistance.

Performance

SpeckEx leverages Rust NIFs for near-native performance. Speck is designed to be one of the fastest software ciphers, particularly on resource-constrained devices.

AES 128/256 block dec:   10_634_359 ops/s
AES 128/256 block enc:   10_525_979 ops/s
Speck 64/128 block enc:  10_150_622 ops/s
Speck 128/256 block enc:  9_726_263 ops/s
Speck 64/128 block dec:   9_674_401 ops/s
Speck 128/256 block dec:  9_094_560 ops/s
Speck 96/144 block enc:   8_703_340 ops/s
Speck 96/144 block dec:   7_582_202 ops/s
AES 128/256 CTR enc:        470_193 ops/s
Speck 128/256 CTR enc:       64_247 ops/s

Run benchmarks with:

mix run benchmark/speck.exs

License

This project is licensed under the Apache 2.0 License - see the LICENSE file for details.

References

Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Acknowledgments