Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- Copyright (C) 2014 Clinton Duclaux [clinton at diceserver dot ca]
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
- associated documentation files (the "Software"), to deal in the Software without restriction,
- including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
- copies of the Software, and to permit persons to whom the Software is furnished to do so,
- subject to the following conditions:
- -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
- -Visible credit is given to the original author.
- -The software is distributed in a non-profit way.
- ---------------------------------------------------------------------------------------------------------------------------------
- This library will do an RC4-256 stream cipher. The function list is as below
- encryptRC4(msg, key) --Encrypts @msg with @key and then does a base32 transform on the output value
- decryptRC4(msg, key) --Decrypts @msg with @key, @msg is first debased32 transformed before it is decrypted
- rc4(msg, key) --Encrypts @msg with @key
- swap (x, y) --Swaps @x and @y
- This is a pure lua implementation of the RC4 stream cipher. This implementation only does raw encryption and decryption.
- That is; it does not have any mechanism upon decryption to ensure that a correct key was used. If an incorrect key
- is used it will give garbage out which may include special character. It is advised you do integrity checking to ensure that
- your decrypted message has been in fact decrypted with a valid key. The output ciphertext will come out base32 encoded. The base32
- encoding IS NOT an encryption mechanism, rather it is a way to make binary data human readable. Conversely when you decrypt a message
- the decryptRC4 function expects a base32 message.
- If you want to deal with the raw RC4 algorithm call the rc4 function directly. The function is the same for both encryption and
- decryption
- **************************************************** SECURITY **************************************************************
- The RC4-256 cipher has several weaknesses that are inherent to Output Feedback mode ciphers. Repeat after me:
- NEVER USE THE SAME KEY TO ENCRYPT TWO DIFFERENT MESSAGES
- If you do, you completely break the security of the system. Here's why: if you have two ciphertext streams, A+K and B+K,
- and you subtract one from the other, you get (A+K)-(B+K) = A+K-B-K = A-B. That's two plaintext streams combined with each other
- with no key involved, and is very easy to break. Trust me on this one: you might not be able to recover A and B from A-B, but a
- professional cryptanalyst can. This is vitally important: never use the same key to encrypt two different messages.
- For more information on this weakness please see the following website, while it speaks to the solitaire cipher it should be noted
- that RC4 like solitaire is an Output Feedback Ciphers.
- https://www.schneier.com/solitaire.html
- Stream ciphers can include other weaknesses such as bit-flipping attacks. Do your research and ensure that this cipher will meet
- your needs. If your trying to protect your messages from your kid brother it will probably be more than enough. If you are trying
- to protect your messages from a motivated government or corporation you would be best advised to look at better ciphers.
- You are responsible for ensuring your keys are strong. As this is a pure implementation nonce's are not implemented. This
- creates a situation where if you use weak keys your encryption may be easily brute forced. It needs to be said again.
- You must use strong keys to prevent brute force attacks.
- ***************************************************************************************************************************
- The following functions are not my work and I give credit where it is due.
- Copyright (C) 2012 Thomas Farr a.k.a tomass1996 [farr.thomas@gmail.com]
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
- associated documentation files (the "Software"), to deal in the Software without restriction,
- including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
- copies of the Software, and to permit persons to whom the Software is furnished to do so,
- subject to the following conditions:
- -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
- -Visible credit is given to the original author.
- -The software is distributed in a non-profit way.
- toBase32(str) --Encodes @str in Base32
- fromBase32(str) --Decodes @str from Base32
- bit.tobits(n) --Transform @n to bits
- bit.tonumb(n) --Transform @tbl bits to number
- bit.bxor(m,n) --Xor's @m, @n bits tables
- bit.checkint(n) --Sanity checks @n to make sure we do a bitwise on a number only
- bit.expand(m, n) --Expands tables so we can xor them
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- ]]--
- function encryptRC4(msg, key)
- return(toBase32(rc4(msg, key)))
- end
- --the decryption is done by RC4, the fromBase32 is only used for human readability
- -- it also has the effect that we don't need to do any escaping of the string when we pass it around
- function decryptRC4(msg, key)
- return(rc4(fromBase32(msg), key))
- end
- function rc4(msg, key)
- --ensure the inputs are strings if they are already not
- str = tostring(str)
- key = tostring(key)
- --Our output string, we will build this as we go when we do our RC4 transform
- out = ""
- --S Boxes, used in keeping track of the key schedule values
- S = {}
- -- Key scheduling
- -- initialize our S table
- for i = 0, 255, 1 do
- S[i] = i
- end
- -- Do the key scheduling, this will use our key to scramble up initalize and scramble the S-Boxes,
- -- The key scheduling does not use a nonce so you as the user are responsible for making sure the
- --keys are strong
- j = 0
- for i = 0, 255, 1 do
- j = (j + S[i] + key:byte((i%key:len())+1))%256
- S[i], S[j] = swap(S[i], S[j]) -- swap S[i] and S[j]
- end
- -- Encrypt/Decrypt our message
- i = 0
- j = 0
- for k = 1, msg:len(), 1 do -- loop k times which is the length of our input
- i = (i + 1) % 256
- j = (j + S[i]) % 256
- S[i], S[j] = swap(S[i], S[j]) -- swap S[i] and S[j]
- K = S[(S[i] + S[j]) % 256]
- --encrypt/decrypt our byte and put into our output string
- out = out .. string.char(bit.bxor(msg:byte(i), K))
- end
- return out
- end
- function swap(x, y)
- return y, x
- end
- --the encryption is done by RC4, the toBase32 is only used to take our string that can include special characters and makes them
- --human readable, it also has the effect that we don't need to do any escaping of the string when we pass it around
- local base32 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
- function toBase32(str) --Encodes @str in Base32
- if not str then return nil end
- str = tostring(str)
- local byte=0
- local bits=0
- local rez=""
- local i=0
- for i = 1, str:len() do
- byte=byte*256+str:byte(i)
- bits=bits+8
- repeat
- bits=bits-5
- local mul=(2^(bits))
- local b32n=math.floor(byte/mul)
- byte=byte-(b32n*mul)
- b32n=b32n+1
- rez=rez..string.sub(base32,b32n,b32n)
- until bits<5
- end
- if bits>0 then
- local b32n= math.fmod(byte*(2^(5-bits)),32)
- b32n=b32n+1
- rez=rez..string.sub(base32,b32n,b32n)
- end
- return rez
- end
- function fromBase32(str) --Decodes @str from Base32
- if not str then return nil end
- str = tostring(str)
- local b32n=0
- local bits=0
- local rez=""
- local i=0
- string.gsub(str:upper(), "["..base32.."]", function (char)
- local num = string.find(base32, char, 1, true)
- b32n=b32n*32+(num - 1)
- bits=bits+5
- while bits>=8 do
- bits=bits-8
- local mul=(2^(bits))
- local byte = math.floor(b32n/mul)
- b32n=b32n-(byte*mul)
- rez=rez..string.char(byte)
- end
- end)
- return rez
- end
- local bit = {}
- bit["tobits"] = function(n)
- bit.checkint(n)
- if(n < 0) then
- return bit.tobits(bit.bnot(math.abs(n)) + 1)
- end
- local tbl = {}
- local cnt = 1
- while (n > 0) do
- local last = math.fmod(n,2)
- if(last == 1) then
- tbl[cnt] = 1
- else
- tbl[cnt] = 0
- end
- n = (n-last)/2
- cnt = cnt + 1
- end
- return tbl
- end
- bit["tonumb"] = function(tbl)
- local n = table.getn(tbl)
- local rslt = 0
- local power = 1
- for i = 1, n do
- rslt = rslt + tbl[i]*power
- power = power*2
- end
- return rslt
- end
- bit["bxor"] = function(m, n)
- local tbl_m = bit.tobits(m)
- local tbl_n = bit.tobits(n)
- bit.expand(tbl_m, tbl_n)
- local tbl = {}
- local rslt = math.max(table.getn(tbl_m), table.getn(tbl_n))
- for i = 1, rslt do
- if(tbl_m[i] ~= tbl_n[i]) then
- tbl[i] = 1
- else
- tbl[i] = 0
- end
- end
- return bit.tonumb(tbl)
- end
- bit["checkint"] = function(n)
- if(n - math.floor(n) > 0) then
- error("trying to use bitwise operation on non-integer!")
- end
- end
- bit["expand"] = function(tbl_m, tbl_n)
- local big = {}
- local small = {}
- if(table.getn(tbl_m) > table.getn(tbl_n)) then
- big = tbl_m
- small = tbl_n
- else
- big = tbl_n
- small = tbl_m
- end
- for i = table.getn(small) + 1, table.getn(big) do
- small[i] = 0
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement