Posted 25 December 2015 - 07:42 AM
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)
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.
Download: pastebin get GPzf9JSa chacha
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 "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 on 12 August 2018 - 06:44 PM