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)
Usage
As 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 output of the function is in the same array format coupled with a __tostring metamethod for easy conversion back into string.
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 output of the function is in the same array format coupled with a __tostring metamethod for easy conversion back into string.
Example
The 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
Edited by Anavrins, 12 August 2018 - 07:44 PM.