Skip to content
master
Switch branches/tags
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
src
 
 
 
 
 
 
 
 
 
 

luazen

Luazen is a small library with various compression, encoding and cryptographic functions for Lua: LZMA, base64 and base58, Chacha20, curve25519 key exchange, ed25519 signature, Blake2b hash, Argon2i key derivation and more...

All the functions work on strings, there is no stream or chunked complex interface. All the code is included. No external dependencies.

Recent changes

October-2020 version 0.16

  • lzma() produces now a compressed format compatible with linux lzma and unlzma commands. So a string compressed by luazen.lzma() can now be uncompressed by the linux unlzma command.

  • The unlzma() luazen function can now uncompress data compressed either in the former luazen format ("legacy") or in the new "standard" format. So user programs will be able to transparently uncompress data compressed with older luazen versions.

  • The file 'lzma_std_fmt.lua' contains more details about both formats and Lua functions to detect the LZMA compression format and convert compressed strings from the legacy to the standard format. This may be useful only for programs still using former luazen versions.

December-2019

  • "Modular build" - instead of including all functions, Luazen can be built à la carte. - see the Build section below. Obsolete/non-functional rockspecs have been removed.

June-2019

  • Added Lzma compression (from the Igor Pavlov 7z 19.0 sources)

March-2019

  • Added Ascon, a selected algorithm in the CAESAR competition for authenticated encryption (the Ascon-128a, 64-bit optimized version)

August-2018

  • Version 0.11 (hopefully the last API modification before v1.0).

    • Blake2b API: removed the chunked interface ('init', 'update' and 'final' functions are combined in one 'blake2b' function).

    • Morus API: switched parameters 'ad' and 'ninc' (homogenized API with Norx and XChacha).

April-2018:

  • The current version is now v0.10. Please note that the library has undergone significant modifications since version 0.9, both implementation and API. Moving toward a good and hopefully stable API before tagging the v1.0.

    • The former version v0.9 is available here or can be installed with luazen-0.9-1.rockspec.
  • Added Morus, a finalist (round 4) in the CAESAR competition for authenticated encryption.

  • The Gimli functions which briefly appeared here have been removed.

March-2018: moving toward v0.10 - some significant changes:

  • The code has been reorganized to make it easier to build variants of the library with an "a la carte" selection of modules

  • Some functions have been renamed (see API below)

  • Added (X)Chacha20-Poly1305 authenticated encryption with additional data (AEAD)

  • all the curve25519 functions are based on the tweetnacl implementation

  • The ed25519 signature functions use sha512 instead of blake2b hash

August-2017

  • Added the amazing BriefLZ compression functions.

Functions

Compression functions include:

  • The tiny LZF library by Marc Alexander Lehmann. It is not as efficient as gzip, but much smaller and very fast.
  • The amazing BriefLZ algorithm by Joergen Ibsen. It is a bit slower than LZF, but the code is even smaller and it achieves a much better compression ratio (better than gzip on some workloads). It could completely replace LZF in future versions of luazen.
  • The ultimate LZMA algorithm by Igor Pavlov of 7z fame. The code is larger than LZF or BriefLZ (it adds ~ 40Kbytes to luazen) but the ratio "code size / compression ratio" outclasses the competition.

Endoding and decoding functions are provided for base64 and base58 (for base58, the BitCoin encoding alphabet is used).

Cryptographic functions include:

  • Morus, a fast authenticated encryption algorithm with associated data (AEAD). Morus is a finalist (round 4) in the CAESAR competition. This is the Morus-1280 variant (160-byte state, 256 and 128-bit key, 128-bit nonce, optimized for 64-bit architectures). Its structure also makes it a very good fit for a pure Lua implmentation.
  • Ascon, one of the slected encryption algorithm with associated data (AEAD) in the CAESAR competition. This is the Ascon-128a variant (64-bit optimized).
  • (X)Chacha20-Poly1305 authenticated encryption with additional data (AEAD).
  • Norx authenticated encryption with additional data (AEAD) - this is the default 64-4-1 variant (256-bit key and nonce, 4 rounds)
  • Blake2b, Sha512 cryptographic hash functions,
  • Argon2i, a modern key derivation function based on Blake2b. Like scrypt, it is designed to be expensive in both CPU and memory.
  • Curve25519-based key exchange and public key encryption,
  • Ed25519-based signature functions.

Legacy cryptographic functions include md5, and rc4 (raw or drop-256 variant).

Luazen borrows heavily from other projects. See the License and credits section below.

API

--- Compression functions

lzma(str)
	compress string str (LZMA algorithm)
	return the compressed string or (nil, error message)

unlzma(cstr)
	uncompress string cstr
	return the uncompressed string or (nil, error message)

blz(str)
	compress string str (BriefLZ algorithm)
	return the compressed string or (nil, error message)

unblz(cstr)
	uncompress string cstr
	return the uncompressed string or (nil, error message)

lzf(str)
	compress string str (LZF algorithm)
	return the compressed string or (nil, error message)

unlzf(cstr)
	uncompress string cstr
	return the uncompressed string or (nil, error message)

--- Encoding functions

b64encode(str [, n])
	base64 encode string str. n is an optional integer
	if n > 0, a newline is inserted every n character in the encoded string
	if n == 0, no newline is inserted.
	if not provided, n defaults to 72.
	return the encoded string

b64decode(bstr)
	decode base64-encoded string bstr. Even non well-formed encoded strings (ie.
	strings with no "=" padding) are decoded.
	all whitespace characters in bstr are ignored.
	return the encoded string or nil if the string cannot be decoded

b58encode(str)
	base58 encode string str
	this uses the same alphabet as bitcoin addresses:
	"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
	contrary to base64, base58 encodes a string as a long number 
	written in base58. 
	Base58 is not intended to be used for long strings, 
	if #str > 256, str is not encoded and the function raises an error.
	No newline is inserted in the encoded string.
	return the encoded string.

b58decode(bstr)
	decode base58-encoded string bstr
	return the decoded string or (nil, error message) in case of an 
	invalid base58 string or if the decoded string is longer than
	256 bytes.

xor(str, key)
	return the byte-to-byte xor of string str with string key.
	the returned string is always the same length as str.
	if key is longer than str, extra key bytes are ignored.
	if key is shorter than str, it is repeated as many times 
	as necessary.

--- Authenticated encryption functions (Morus encryption algorithm)

morus_encrypt(encrypt(k, n, m [, ninc [, ad]]) return c
	k: key string (16 or 32 bytes)
	n: nonce string (16 bytes)
	m: message (plain text) string 
	ninc: optional nonce increment (useful when encrypting a long message
	     as a sequence of block). The same parameter n can be used for 
	     the sequence. ninc is added to n for each block, so the actual
	     nonce used for each block encryption is distinct.
	     ninc defaults to 0 (the nonce n is used as-is)
	ad: prefix additional data (AD) (not encrypted, prepended to the 
	     encrypted message). default to the empty string
	return encrypted text string c with ad prefix (c includes 
	the 16-byte MAC, so #c = #ad + #m + 16)

morus_decrypt(k, n, c [, ninc [, adln]]) 
	return m | (nil, msg)
	k: key string (16 or 32 bytes)
	n: nonce string (16 bytes)
	c: encrypted message string 
	ninc: optional nonce increment (see above. defaults to 0)
	adln: length of the AD prefix (default to 0)
	return decrypted message m or (nil, errmsg) if MAC is not valid

--- Authenticated encryption functions (Ascon-128a encryption algorithm)

ascon_encrypt(encrypt(k, n, m [, ninc [, ad]]) return c
	k: key string (16 bytes)
	n: nonce string (16 bytes)
	m: message (plain text) string 
	ninc: optional nonce increment (useful when encrypting a long message
	     as a sequence of block). The same parameter n can be used for 
	     the sequence. ninc is added to n for each block, so the actual
	     nonce used for each block encryption is distinct.
	     ninc defaults to 0 (the nonce n is used as-is)
	ad: prefix additional data (AD) (not encrypted, prepended to the 
	     encrypted message). default to the empty string
	return encrypted text string c with ad prefix (c includes 
	the 16-byte MAC, so #c = #ad + #m + 16)

ascon_decrypt(k, n, c [, ninc [, adln]]) 
	return m | (nil, msg)
	k: key string (16 bytes)
	n: nonce string (16 bytes)
	c: encrypted message string 
	ninc: optional nonce increment (see above. defaults to 0)
	adln: length of the AD prefix (default to 0)
	return decrypted message m or (nil, errmsg) if MAC is not valid

--- Authenticated encryption functions (Norx encryption algorithm)

norx_encrypt(encrypt(k, n, m [, ninc [, aad [, zad]]]) return c
	k: key string (32 bytes)
	n: nonce string (32 bytes)
	m: message (plain text) string 
	ninc: optional nonce increment (useful when encrypting a long message
	     as a sequence of block). The same parameter n can be used for 
	     the sequence. ninc is added to n for each block, so the actual
	     nonce used for each block encryption is distinct.
	     ninc defaults to 0 (the nonce n is used as-is)
	aad: prefix additional data (AD) (not encrypted, prepended to the 
	     encrypted message). default to the empty string
	zad: suffix additional data (not encrypted, appended to the 
	     encrypted message). default to the empty string
	return encrypted text string c with aad prefix and zad suffix
	(c includes the 32-byte MAC, so #c = #aad + #m + 32 + #zad)

norx_decrypt(k, n, c [, ninc [, aadln [, zadln]]]) 
	    return (m, aad, zad) | (nil, msg)
	k: key string (32 bytes)
	n: nonce string (32 bytes)
	c: encrypted message string 
	ninc: optional nonce increment (see above. defaults to 0)
	aadln: length of the AD prefix (default to 0)
	zadln: length of the AD suffix  (default to 0)
	return (plain text, aad, zad) or (nil, errmsg) if MAC is not valid

--- Authenticated encryption functions ((x)chacha20 encryption algorithm
    with a poly1305 MAC)

xchacha_encrypt(encrypt(k, n, m [, ninc [, aad]]) return c
	k: key string (32 bytes)
	n: nonce string (24 bytes)
	m: message (plain text) string 
	ninc: optional nonce increment (useful when encrypting a long message
	     as a sequence of block). The same parameter n can be used for 
	     the sequence. ninc is added to n for each block, so the actual
	     nonce used for each block encryption is distinct.
	     ninc defaults to 0 (the nonce n is used as-is)
	aad: prefix additional data (AD) (not encrypted, prepended to the 
	     encrypted message). default to the empty string
	return encrypted text string c with aad prefix and zad suffix
	(c includes the 16-byte MAC, so #c = #aad + #m + 16)

xchacha_decrypt(k, n, c [, ninc [, aadln ]]) 
	    return (m, aad) | (nil, msg)
	k: key string (32 bytes)
	n: nonce string (24 bytes)
	c: encrypted message string 
	ninc: optional nonce increment (see above. defaults to 0)
	aadln: length of the AD prefix (default to 0)
	return (plain text, aad) or (nil, errmsg) if MAC is not valid


--- Curve25519-based key exchange

x25519_public_key(sk) => pk
	return the public key associated to a curve25519 secret key
	sk is the secret key as a 32-byte string
	pk is the associated public key as a 32-byte string

keypair() has been removed to eliminate hard dependency to 
the included randombyte() function. It can be replaced with:
	function keypair()
		local sk = luazen.randombytes(32)
		return luazen.ec25519_public_key(sk), sk
	end

x25519_shared_secret(sk, pk) => ss
	DH key exchange. Return a common shared secret ss.
	the shared secret is a 32-byte string. It could be used as-is
	or passed to a derivation function to generate a temporary
	session key.
	sk is the secret key of the party invoking the function 
	("our secret key"). 
	pk is the public key of the other party 
	("their public key").
	sk, pk and ss are 32-byte strings


--- Ed25519 signature

x25519_sign_public_key(sk) => pk
	return the public key associated to a secret key
	sk is the secret key as a 32-byte string
	pk is the associated public key as a 32-byte string

sign_keypair() has been removed to eliminate hard dependency to 
the included randombyte() function. It can be replaced with:
	function keypair()
		local sk = luazen.randombytes(32)
		return luazen.ed25519_public_key(sk), sk
	end

x25519_sign(sk, pk, text) => signed text
	sign a text with a secret key
	sk is the secret key as a 32-byte string
	pk is the public key as a 32-byte string
	text is the text to sign as a string
	Return the signed text which contains  a 64-byte signature
	followed by the original text.

x25519_sign_open(stext, pk) => text
	check a text signature with a public key
	stext is the signed text to verify
	pk is the public key as a 32-byte string
	if the signature is valid, return the original text, or (nil, errmsg)
	
	Note: curve25519 key pairs cannot be used for ed25519 signature. 
	
x25519_sha512(s) => hash
	return the sha512 hash of a string (as a 64-byte binary string)


--- Blake2b cryptographic hash

blake2b(text [, digest_size [, key]]) => digest
	compute the hash of string 'text'.
	'digest_size' is the optional length of the expected digest. If
	provided, it must be an integer between 1 and 64. It defaults to 64.
	'key' is an optional key allowing to use blake2b as a MAC function.
	If provided, key length must be between 1 and 64. 
	The default is no key.
	Returns the hash as a 'digest_size'-long string


--- Argon2i password derivation 

argon2i(pw, salt, nkb, niter) => k
	compute a key given a password and some salt
	This is a password key derivation function similar to scrypt.
	It is intended to make derivation expensive in both CPU and memory.
	pw: the password string
	salt: some entropy as a string (typically 16 bytes)
	nkb:  number of kilobytes used in RAM (as large as possible)
	niter: number of iterations (as large as possible, >= 10)
	Return k, a key string (32 bytes).

	For example: on a CPU i5 M430 @ 2.27 GHz laptop,
	with nkb=100000 (100MB) and niter=10, the derivation takes ~ 1.8 sec
	
	Note: this implementation has no threading support, so no parallel 
	execution.


--- Legacy cryptographic functions

rc4raw(str, key) => encrypted (or decrypted) string
	encrypt (or decrypt, as rc4 is symmetric) string str with string key
	key length must be 16 (or an error is raised)
	return the encrypted string
	see http://en.wikipedia.org/wiki/RC4 for raw rc4 weaknesses
	rc4(), a rc4-drop implementation, should be used instead for most uses

rc4(str, key) => encrypted (or decrypted) string
	this is a rc4-drop encryption function with a 256-byte drop
	(ie. the rc4 state is initialized by "encrypting" a 256-byte block of
	zero bytes before starting the encyption of the string)
	arguments and return are the same as rc4raw()
	key length must be 16 (or an error is raised)

md5(str) => digest
	return the md5 hash of string str as a 16-byte binary string
	(no hex encoding)


--- Misc functions

randombytes(n)
	return a random string of length n generated by the OS RNG 
	(/dev/urandom on Linux, or CryptGenRandom() on Windows)


Modular build

Constants can be defined at compile time to include the corresponding groups of functions in the luazen library (check the Makefile and src.luazen/luazen.c). It allows to build a smaller luazen library containing only the required functions.

The constants and the corresponding groups of functions are listed below:

  BASE64     Base64 encode/decode
  BASE58     Base58 encode/decode
  BLZ        BriefLZ compress/uncompress
  LZF        LZF compress/uncompress
  LZMA       LZMA compress/uncompress
  NORX       Norx AEAD encrypt/decrypt
  CHACHA     Xchacha20 AEAD encrypt/decrypt
  RC4        RC4 encrypt/decrypt
  MD5        MD5 hash
  BLAKE      Blake2b hash, Argon2i key derivation
  SHA2       SHA2-512 hash
  X25519     Ec25519 key exchange and ed25519 signature functions
  MORUS      Morus AEAD encrypt/decrypt
  ASCON      Ascon128a AEAD encrypt/decrypt

The constants are defined in the Makefile in the variable FUNCS.

The provided Makefile defines all the constants, so the default build includes all the functions

A specific build containing for example Chacha20 encryption, SHA-512 hash and curve 25519 public key crypto can be defined with:

FUNCS= -DCHACHA -DSHA2 -DX25519

Once the FUNCS variable is set in the Makefile, the library is built with:

make

Simple tests of the included functions can be run with:

make test

Rockspec files are also provided to build the current luazen version (v0.15) and the last github version with Luarocks:

	# build version 0.15:
	luarocks build luazen-0.15-1.rockspec
	
	# build last github version 
	luarocks build luazen-scm-1.rockspec

The provided rockspec files build luazen with all functions included. The list of included functions can be adjusted by modifyng the following element in the rockspec file: defines = { "_7ZIP_ST", "BASE64", "LZMA", "MD5", "BLAKE", "X25519", "MORUS", "CHACHA", "BASE58", "BLZ", "LZF", "NORX", "ASCON", "RC4" }

The "_7ZIP_ST" definition must be kept. Any other definition can be removed to remove the correponding group of functions in luazen.

License and credits

Luazen is distributed under the terms of the MIT License.

The luazen library includes some code from various authors (see src/):

See src/crypto_licenses.md.

(the code from these sources has been more or less modified - all bugs are probably mine!)

Copyright (c) 2019 Phil Leblanc

About

Compression, encoding and crypto for Lua: LZMA, Chacha20, curve25519, ed25519 signature, Blake2b, Argon2i key derivation and more...

Resources

License

Packages

No packages published

Languages