sparx

Package Version Hex Docs

A pure Gleam implementation of the SPARX family of lightweight block ciphers, designed by Leo Perrin and Daniel Dinu at CryptoLUX (University of Luxembourg).

All three official variants are implemented and verified against the reference test vectors:

VariantBlock sizeKey size
sparx6464-bit128-bit
sparx128_128128-bit128-bit
sparx128_256128-bit256-bit

Installation

gleam add sparx@1

Usage

Keys and plaintexts are represented as tuples of Uint16 values (16-bit words in little-endian order). Use sparx/uint16.unsafe_from_int to construct them from integer literals.

SPARX-64/128

64-bit block, 128-bit key.

import sparx/sparx64
import sparx/uint16

pub fn main() {
  let key =
    sparx64.key_schedule(#(
      uint16.unsafe_from_int(0x0011),
      uint16.unsafe_from_int(0x2233),
      uint16.unsafe_from_int(0x4455),
      uint16.unsafe_from_int(0x6677),
      uint16.unsafe_from_int(0x8899),
      uint16.unsafe_from_int(0xaabb),
      uint16.unsafe_from_int(0xccdd),
      uint16.unsafe_from_int(0xeeff),
    ))

  let plaintext = #(
    uint16.unsafe_from_int(0x0123),
    uint16.unsafe_from_int(0x4567),
    uint16.unsafe_from_int(0x89ab),
    uint16.unsafe_from_int(0xcdef),
  )

  let ciphertext = sparx64.sparx_encrypt(plaintext, key)
  // -> #(0x2bbe, 0xf152, 0x01f5, 0x5f98)

  let recovered = sparx64.sparx_decrypt(ciphertext, key)
  // -> plaintext
}

SPARX-128/128

128-bit block, 128-bit key.

import sparx/sparx128_128
import sparx/uint16

pub fn main() {
  let key =
    sparx128_128.key_schedule(#(
      uint16.unsafe_from_int(0x0011),
      uint16.unsafe_from_int(0x2233),
      uint16.unsafe_from_int(0x4455),
      uint16.unsafe_from_int(0x6677),
      uint16.unsafe_from_int(0x8899),
      uint16.unsafe_from_int(0xaabb),
      uint16.unsafe_from_int(0xccdd),
      uint16.unsafe_from_int(0xeeff),
    ))

  let plaintext = #(
    uint16.unsafe_from_int(0x0123),
    uint16.unsafe_from_int(0x4567),
    uint16.unsafe_from_int(0x89ab),
    uint16.unsafe_from_int(0xcdef),
    uint16.unsafe_from_int(0xfedc),
    uint16.unsafe_from_int(0xba98),
    uint16.unsafe_from_int(0x7654),
    uint16.unsafe_from_int(0x3210),
  )

  let ciphertext = sparx128_128.sparx_encrypt(plaintext, key)
  // -> #(0x1cee, 0x7540, 0x7dbf, 0x23d8, 0xe0ee, 0x1597, 0xf428, 0x52d8)

  let recovered = sparx128_128.sparx_decrypt(ciphertext, key)
  // -> plaintext
}

SPARX-128/256

128-bit block, 256-bit key.

import sparx/sparx128_256
import sparx/uint16

pub fn main() {
  let key =
    sparx128_256.key_schedule(#(
      uint16.unsafe_from_int(0x0011),
      uint16.unsafe_from_int(0x2233),
      uint16.unsafe_from_int(0x4455),
      uint16.unsafe_from_int(0x6677),
      uint16.unsafe_from_int(0x8899),
      uint16.unsafe_from_int(0xaabb),
      uint16.unsafe_from_int(0xccdd),
      uint16.unsafe_from_int(0xeeff),
      uint16.unsafe_from_int(0xffee),
      uint16.unsafe_from_int(0xddcc),
      uint16.unsafe_from_int(0xbbaa),
      uint16.unsafe_from_int(0x9988),
      uint16.unsafe_from_int(0x7766),
      uint16.unsafe_from_int(0x5544),
      uint16.unsafe_from_int(0x3322),
      uint16.unsafe_from_int(0x1100),
    ))

  let plaintext = #(
    uint16.unsafe_from_int(0x0123),
    uint16.unsafe_from_int(0x4567),
    uint16.unsafe_from_int(0x89ab),
    uint16.unsafe_from_int(0xcdef),
    uint16.unsafe_from_int(0xfedc),
    uint16.unsafe_from_int(0xba98),
    uint16.unsafe_from_int(0x7654),
    uint16.unsafe_from_int(0x3210),
  )

  let ciphertext = sparx128_256.sparx_encrypt(plaintext, key)
  // -> #(0x3328, 0xe637, 0x14c7, 0x6ce6, 0x32d1, 0x5a54, 0xe4b0, 0xc820)

  let recovered = sparx128_256.sparx_decrypt(ciphertext, key)
  // -> plaintext
}

API Reference

Full documentation is available on hexdocs.pm/sparx.

sparx64

FunctionSignatureDescription
key_schedule(Masterkey) -> SubkeysDerives subkeys from a 128-bit master key (8-tuple of Uint16)
sparx_encrypt(Plaintext, Subkeys) -> PlaintextEncrypts a 64-bit block (4-tuple of Uint16)
sparx_decrypt(Plaintext, Subkeys) -> PlaintextDecrypts a 64-bit block

sparx128_128

FunctionSignatureDescription
key_schedule(Masterkey) -> SubkeysDerives subkeys from a 128-bit master key (8-tuple of Uint16)
sparx_encrypt(Plaintext, Subkeys) -> PlaintextEncrypts a 128-bit block (8-tuple of Uint16)
sparx_decrypt(Plaintext, Subkeys) -> PlaintextDecrypts a 128-bit block

sparx128_256

FunctionSignatureDescription
key_schedule(Masterkey) -> SubkeysDerives subkeys from a 256-bit master key (16-tuple of Uint16)
sparx_encrypt(Plaintext, Subkeys) -> PlaintextEncrypts a 128-bit block (8-tuple of Uint16)
sparx_decrypt(Plaintext, Subkeys) -> PlaintextDecrypts a 128-bit block

Security Notice

This library is a reference implementation for educational and research purposes. It has not been independently audited. Do not use it to protect sensitive data in production without a thorough security review.

References

Development

gleam test  # Run the tests
gleam build # Build the project

License

LGPL-3.0-or-later

Search Document