ChaCha20 is mostly considered as a secure replacement to the broken RC4 algorithm.
It is slower but more secure than RC4, however it is faster than AES.
This is based off the implementation in this ietf draft (https://tools.ietf.o...a20-poly1305-01)

UsageAs with any stream ciphers, encryption and decryption are done in exactly the same way, encrypting a plaintext will give you a ciphertext, re-encrypting that ciphertext with the same settings will give you the plaintext back.
The only function, "crypt", takes 3 main arguments, and two optional.
crypt(data, key, nonce, counter, round)

The type of data that must be passed is an array of 8-bits values per indexes, example the string "hello world" would be {0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64}
Strings can be easily converted into this format by doing {str:byte(1,-1)}, and can be as easily converted back into string with string.char(unpack(data))
  • The "data" argument is your data that you want to encrypt, and can take both an 8-bits array and a string as an input.
  • The "key" argument is your secret key, its size can be either 128-bits (16 bytes) or 256-bits (32 bytes), a 256-bits key is recommended and does not make the algorithm run slower than with an 128-bits one.
  • The "nonce" argument is a public, random nonce, it must be 96-bits (12 bytes), this value should be different for every messages transmitted, see example below.
  • The "counter" argument is optional, defaulted to 1, is the starting point of the counter used by the cipher.
  • The "round" argument is optional, default is 20, is the amount of rounds that the algorithm does, other standardized amounts are 8 and 12, less rounds runs faster at the slight cost of security.
The key and the nonce should be formatted in the same array format explained above.
The output of the function is in the same array format coupled with a __tostring metamethod for easy conversion back into string.

ExampleThe preferable way of implementing most ciphers for modem transmission is the following

os.loadAPI("chacha")
local random = math.random
local key = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31} #-- Generate your own random key
#-- Little utility function for easy nonce generation
local function gen_nonce(size)
  local n = {}
  for i = 1, size do n[#n+1] = random(0, 255) end
  return n
end

local function encrypt(msg)
  local nonce = gen_nonce(12)
  local ctx = chacha.crypt(msg, key, nonce)
  return { nonce, ctx }
end

local function decrypt(msg)
  local nonce = msg[1]
  local ctx = msg[2]
  return chacha.crypt(ctx, key, nonce)
end

#-- Sending
local message = "hello world"
transmit( encrypt(message) )

#-- Receiving
local e = {os.pullEvent("modem_message")}
local msg = e[5]
local receivedMsg = decrypt(msg)

Download: pastebin get GPzf9JSa chacha