Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- RSA_Encrypt = {}
- --used for encoding strings to prepare them for encryption
- -- the mathematical max is 25, higher numbers will cause an overflow
- -- and lead to invalid results.
- RSA_Encrypt.max_chars_per_bignum = 25
- BigNumAPIPath = "api/BigNum"
- BigNum = require(BigNumAPIPath)
- --Usage Information:
- --
- -- Tested with 256 bit keys, I wouldn't recommend using keys of 512 or 1024 bit length
- --
- -- important: You must download the BigNum api from:
- -- https://github.com/ennorehling/euler/blob/master/BigNum.lua
- -- you can set the path to the BigNum api at the top
- -- !!!!!!! VERY IMPORTANT: !!!!!!!
- -- after downloading the BigNum api, you must open the file and write:
- -- return BigNum
- -- at the end of the file.
- -- To use this api, you will first need your key pairs generated by a different program.
- --
- -- Load public keys using the loadPublicKeyFrom functions
- -- Load private keys using the loadPrivateKeyFrom functions
- -- To encrypt a string refer to the encryptStringWith.. functions
- -- To decrypt a string refer to the decryptStringWith.. functions
- -- Important:
- -- use the prepareNumber(msg) function to convert your number
- -- to the format used in the encrypt/decrypt functions
- --
- -- To encrypt a number, refer to the encryptWith.. functions
- -- To decrypt a number, refer to the decryptWith.. functions
- --
- --############ Begin Functions ############--
- --
- -- Description:
- -- encrypts a string using the public key
- --
- -- Parameters:
- -- msg => String: the msg to be encrypted
- -- pub_key => PubKey: the public key
- --
- -- Returns:
- -- String: encrypted message ready for broadcasting
- --
- function RSA_Encrypt.encryptStringWithPublicKey(msg,pub_key)
- if msg == nil then
- error("Invalid Parameter #1: msg")
- end
- if pub_key == nil then
- error("Invalid Parameter #2: pub_key")
- end
- local result = ""
- local words = {}
- local bignums = {}
- --split msg into [max_chars_per_bignum]-char strings
- while #msg > RSA_Encrypt.max_chars_per_bignum do
- table.insert(words,msg:sub(1,25))
- msg = msg:sub(26,#msg)
- end
- if #msg > 0 then
- table.insert(words,msg)
- end
- local char_size = BigNum.new(256)
- --encode each word into BigNums (bitshift encoding)
- for i=1, #words do
- --for each char in words[i]
- local bignum = BigNum.new()
- for c=1, #words[i] do
- local byte = BigNum.new( string.byte(words[i]:sub(c,c)) )
- bignum = bignum*char_size + byte
- end
- bignum = RSA_Encrypt.encryptWithPublicKey(bignum,pub_key)
- table.insert(bignums, bignum)
- result = result..tostring(bignum).." "
- end
- return result
- end
- --
- -- Description:
- -- encrypts a string using the private key
- --
- -- Parameters:
- -- msg => String: the msg to be encrypted
- -- pub_key => PubKey: the public key
- --
- -- Returns:
- -- String: encrypted message ready for broadcasting
- --
- function RSA_Encrypt.encryptStringWithPrivateKey(msg,priv_key,pub_key)
- if msg == nil then
- error("Invalid Parameter #1: msg")
- end
- if priv_key == nil then
- error("Invalid Parameter #2: priv_key")
- end
- if pub_key == nil then
- error("Invalid Parameter #3: pub_key")
- end
- local result = ""
- local words = {}
- local bignums = {}
- --split msg into [max_chars_per_bignum]-char strings
- while #msg > RSA_Encrypt.max_chars_per_bignum do
- table.insert(words,msg:sub(1,25))
- msg = msg:sub(26,#msg)
- end
- if #msg > 0 then
- table.insert(words,msg)
- end
- local char_size = BigNum.new(256)
- --encode each word into BigNums (bitshift encoding)
- for i=1, #words do
- --for each char in words[i]
- local bignum = BigNum.new()
- for c=1, #words[i] do
- local byte = BigNum.new( string.byte(words[i]:sub(c,c)) )
- bignum = bignum*char_size + byte
- end
- bignum = RSA_Encrypt.encryptWithPrivateKey(bignum,priv_key,pub_key)
- table.insert(bignums, bignum)
- result = result..tostring(bignum).." "
- os.sleep(0.001)
- end
- return result
- end
- -- Description:
- -- Decrypts a string (encrypted with a private key) using a public key
- -- useful for verifying the message came from a particular sender.
- -- because a message encrypted with someone's private key can be decrypted with
- -- their public key. Very cool!
- --
- -- Paramters:
- -- msg => String: the encrypted message
- -- pub_key => BigNum: the public key n component
- -- pub_e => BigNum: the public key e component
- --
- -- Returns:
- -- String: the decrypted message
- --
- function RSA_Encrypt.decryptStringWithPublicKey(msg,pub_key)
- if msg == nil then
- error("Invalid Parameter #1: msg")
- end
- if pub_key == nil then
- error("Invalid Parameter #2: pub_key")
- end
- --decode bignum into string
- msg = RSA_Encrypt.splitWords(msg)
- local result = ""
- local bignums = {}
- for i=1, #msg do
- local bignum = BigNum.new(msg[i])
- bignum = RSA_Encrypt.decryptWithPublicKey(bignum,pub_key)
- table.insert(bignums, bignum)
- end
- local char_size = BigNum.new(256)
- local _0 = BigNum.new(0)
- --decode the decrypted bignums into strings (bitshift encoded)
- for i=1, #bignums do
- local word = ""
- while bignums[i] > _0 do
- local tmp = BigNum.new()
- local char = BigNum.new()
- BigNum.div(bignums[i],char_size,tmp,char)
- word = string.char( tonumber(tostring(char)) )..word
- BigNum.copy(tmp,bignums[i])
- end
- result = result..word
- os.sleep(0.001)
- end
- return result
- end
- -- Description:
- -- Decrypts a string (encrypted with a public key) using a private key
- --
- -- Paramters:
- -- msg => String: the encrypted message
- -- priv_key => BigNum: the private key.
- -- pub_key => PubKey: the public key
- --
- -- Returns:
- -- String: the decrypted message
- --
- function RSA_Encrypt.decryptStringWithPrivateKey(msg,priv_key,pub_key)
- if msg == nil then
- error("Invalid Parameter #1: msg")
- end
- if priv_key == nil then
- error("Invalid Parameter #2: priv_key")
- end
- if pub_key == nil then
- error("Invalid Parameter #3: pub_key")
- end
- --decode bignum into string
- msg = RSA_Encrypt.splitWords(msg)
- local result = ""
- local bignums = {}
- for i=1, #msg do
- local bignum = BigNum.new(msg[i])
- bignum = RSA_Encrypt.decryptWithPrivateKey(bignum,priv_key,pub_key)
- table.insert(bignums, bignum)
- os.sleep(0.001)
- end
- local char_size = BigNum.new(256)
- local _0 = BigNum.new(0)
- --decode the decrypted bignums into strings (bitshift encoded)
- for i=1, #bignums do
- local word = ""
- while bignums[i] > _0 do
- local tmp = BigNum.new()
- local char = BigNum.new()
- BigNum.div(bignums[i],char_size,tmp,char)
- word = string.char( tonumber(tostring(char)) )..word
- BigNum.copy(tmp,bignums[i])
- end
- result = result..word
- end
- return result
- end
- --
- -- Description:
- -- convert public key to a one line string for sending over modems
- --
- -- Parameters:
- -- pub_key => PubKey: the public key
- --
- -- Returns:
- -- String: the public key for broadcasting
- --
- function RSA_Encrypt.publicKeyToString(_pub_key)
- if _pub_key == nil then
- error("Invalid Parameter #1: _pub_key")
- end
- local pub_key = _pub_key[1]
- local pub_e = _pub_key[2]
- local result = tostring(pub_key).." "..tostring(pub_e)
- return result
- end
- --
- -- Description:
- -- Load public key from path
- -- File @ path should contain:
- -- RSA n component on first line
- -- RSA e component on second line
- --
- -- Parameter:
- -- path => path to file containing RSA public key data
- --
- -- Returns:
- -- pub_key ==> a BigNum RSA n component
- -- pub_e ==> a BigNum RSA e component
- --
- function RSA_Encrypt.loadPublicKeyFromFile(path)
- if path == nil then
- error("Invalid Parameter #1: path")
- end
- if fs.exists(path) then
- local pub_key_file = fs.open(path,"r")
- local pub_key = pub_key_file.readLine()
- local pub_e = pub_key_file.readLine()
- pub_key = BigNum.new(pub_key)
- pub_e = BigNum.new(pub_e)
- return {pub_key, pub_e}
- else
- error("pubkey file not found")
- end
- end
- --
- -- Description:
- -- creates and returns the e and n component of an RSA Public Key from a string.
- -- the format of the string should be:
- -- pub_key.." "..pub_e
- -- where pub_key is the n component and pub_e is the e component of an RSA Public Key
- --
- -- Parameters:
- -- str ==> a string containing the public key data
- --
- -- Returns:
- -- pub_key ==> a BigNum, the n component of an RSA Public Key
- -- pub_e ==> a BigNum, the e component of an RSA Public Key
- --
- function RSA_Encrypt.loadPublicKeyFromString(str)
- if str == nil then
- error("Invalid Parameter #1: str")
- end
- local words = RSA_Encrypt.splitWords(str)
- local pub_key = BigNum.new(words[1])
- local pub_e = BigNum.new(words[2])
- return {pub_key, pub_e}
- end
- --
- -- Description:
- -- Load private key from path
- -- File @ path should contain:
- -- RSA d component
- --
- -- Parameter:
- -- path => path to file containing RSA private key
- --
- -- Returns:
- -- priv_key => a BigNum containing the RSA private key found in path
- --
- function RSA_Encrypt.loadPrivateKeyFromFile(path)
- if path == nil then
- error("Invalid Parameter #1: path")
- end
- if fs.exists(path) then
- priv_key_file = fs.open(path,"r")
- priv_key = priv_key_file.readLine()
- priv_key = BigNum.new(priv_key)
- return priv_key
- else
- error("privkey file not found")
- end
- end
- --
- -- Description:
- -- Load private key from str
- --
- -- Parameter:
- -- str => a string containing an RSA Private Key (base 10)
- --
- -- Returns:
- -- priv_key => a BigNum containing the RSA private key found in path
- --
- function RSA_Encrypt.loadPrivateKeyFromString(str)
- if str == nil then
- error("Invalid Parameter #1: str")
- end
- priv_key = BigNum.new(str)
- return priv_key
- end
- --
- -- Description:
- -- Encrypt msg with a given public key
- --
- -- Parameters:
- -- msg ==> a BigNum to be encrypted
- -- pub_key ==> a BigNum, the n component of RSA pub key
- -- pub_e ==> a BigNum, the e component of RSA pub key
- --
- -- Returns:
- -- a BigNum: msg encrypted with the pub key
- --
- function RSA_Encrypt.encryptWithPublicKey(msg, _pub_key)
- if msg == nil then
- error("Invalid Parameter #1: msg")
- end
- if _pub_key == nil then
- error("Invalid Parameter #2: _pub_key")
- end
- local pub_key = _pub_key[1]
- local pub_e = _pub_key[2]
- local result = RSA_Encrypt.BigNumModPow(msg, pub_e, pub_key)
- return result
- end
- --
- -- Description:
- -- Encrypt msg with a given private key
- --
- -- Parameters:
- -- msg ==> a BigNum to be encrypted
- -- priv_key ==> a BigNum, the RSA private key
- -- pub_key ==> a BigNum, the n component of RSA public key
- --
- -- Returns:
- -- a BigNum: msg encrypted with the pub key
- --
- function RSA_Encrypt.encryptWithPrivateKey(msg, priv_key, _pub_key)
- if msg == nil then
- error("Invalid Parameter #1: msg")
- end
- if priv_key == nil then
- error("Invalid Parameter #2: priv_key")
- end
- if _pub_key == nil then
- error("Invalid Parameter #3: _pub_key")
- end
- local pub_key = _pub_key[1]
- local result = RSA_Encrypt.BigNumModPow(msg, priv_key, pub_key)
- return result
- end
- --
- -- Description:
- -- decrypt msg (encrypted with a public key) using the private key
- --
- -- Parameters:
- -- msg ==> a BigNum, the msg to be decrypted
- -- priv_key ==> a BigNum, the RSA private key
- -- pub_key ==> PubKey: the public key
- --
- -- Returns:
- -- a BigNum, the decrypted msg
- --
- function RSA_Encrypt.decryptWithPrivateKey(msg, priv_key, _pub_key)
- if msg == nil then
- error("Invalid Parameter #1: msg")
- end
- if priv_key == nil then
- error("Invalid Parameter #2: priv_key")
- end
- if _pub_key == nil then
- error("Invalid Parameter #3: _pub_key")
- end
- local pub_key = _pub_key[1]
- local result = RSA_Encrypt.BigNumModPow(msg, priv_key, pub_key)
- return result
- end
- --
- -- Description:
- -- decrypt msg (encrypted with a private key) using the public key
- --
- -- Parameters:
- -- msg ==> a BigNum, the msg to be decrypted
- -- _pub_key ==> a BigNum, the n component of an RSA Public Key
- --
- -- Returns:
- -- the decrypted message in msg.
- function RSA_Encrypt.decryptWithPublicKey(msg, _pub_key)
- if msg == nil then
- error("Invalid Parameter #1: msg")
- end
- if _pub_key == nil then
- error("Invalid Parameter #2: _pub_key")
- end
- local pub_key = _pub_key[1]
- local pub_e = _pub_key[2]
- local result = RSA_Encrypt.BigNumModPow(msg, pub_e, pub_key)
- return result
- end
- --
- -- Description:
- -- creates and returns a BigNum from msg
- --
- -- Parameter:
- -- msg ==> a string containing an integer (base 10) OR an int
- --
- -- Returns:
- -- a BigNum, the integer contained in msg
- --
- function RSA_Encrypt.prepareNumber(num)
- if num == nil then
- error("Invalid Parameter #1: num")
- end
- local result = BigNum.new(num)
- return result
- end
- --
- -- Description:
- -- returns num^exponent % modulo
- --
- -- Parameters:
- -- b = a BigNum to be modpow-ed
- -- e = a BigNum exponent
- -- m = a BigNum modulo
- --
- -- Returns:
- -- a BigNum == (base^exponent) % modulo
- --
- function RSA_Encrypt.BigNumModPow(b, e, m)
- if b == nil then
- error("Invalid Parameter #1: b")
- end
- if e == nil then
- error("Invalid Parameter #2: e")
- end
- if m == nil then
- error("Invalid Parameter #3: m")
- end
- base = BigNum.new()
- exponent = BigNum.new()
- modulo = BigNum.new()
- BigNum.copy(b, base)
- BigNum.copy(e, exponent)
- BigNum.copy(m, modulo)
- --represent 0, 1, and 2 as BigNums
- local _2 = BigNum.new("2")
- local _1 = BigNum.new("1")
- local _0 = BigNum.new("0")
- --if base == 1
- if BigNum.eq(base,_1) then
- return 0
- end
- local r = BigNum.new("1")
- --base = base % modulo
- local tmp = BigNum.new()
- local tmp_res = BigNum.new()
- local tmp_res_2 = BigNum.new()
- --base = base % modulo
- BigNum.div(base, modulo, tmp, tmp_res)
- BigNum.copy(tmp_res,base)
- --while exponent > 0
- while (BigNum.compare(exponent, _0) == 1) do
- --if exponent % 2 == 1 then
- BigNum.div(exponent, _2, tmp, tmp_res)
- if (BigNum.compare(tmp_res, _1) == 0) then
- --r = (r*base) % modulo
- BigNum.mul(r,base,tmp_res)
- BigNum.div(tmp_res,modulo,tmp,tmp_res_2)
- BigNum.copy(tmp_res_2,r)
- end
- -- base = (base*base) % m
- BigNum.mul(base,base,tmp_res)
- BigNum.div(tmp_res,modulo,tmp,tmp_res_2)
- BigNum.copy(tmp_res_2,base)
- -- e = math.floor(e/2)
- BigNum.div(exponent,_2,tmp_res,tmp)
- BigNum.copy(tmp_res,exponent)
- end
- return r
- end
- --
- -- a helper function used by RSA_Encrypt.loadPublicKeyFromString(str)
- --
- function RSA_Encrypt.splitWords(s)
- if s == nil then
- error("Invalid Parameter #1: s")
- end
- local words = {}
- local j = 1
- local btoi = {[true]=1,[false]=0}
- for i = 1, #s do
- b = i ~= #s
- if string.sub(s,i,i) == " " or not b then
- words[#words+1] = string.sub(s,j,i-1*btoi[b])
- j=i+1
- end
- end
- return words
- end
- --
- -- Run a benchmark of the encryStringWith and decryptStringWith functions
- --
- -- Paramter: str => (Optional) the string to run the benchmark on
- --
- function RSA_Encrypt.benchmark(str)
- print("\nRunning Benchmark using:")
- if str == nil then
- str = "Hello world! This is the default benchmark string. You can run the benchmark with a custom string by adding it to the call parameters"
- end
- print(str.."\n")
- local priv_key = BigNum.new("30718027764395347858436300176794542038442961471507061849584361239819342178987")
- local pub_key = RSA_Encrypt.loadPublicKeyFromString("18430816658637208715061780106076725223340967021069964147042057987714753676151 3")
- --
- print("Encrypting with public key:")
- local start = os.epoch("utc")
- local cipher = RSA_Encrypt.encryptStringWithPublicKey(str,pub_key)
- local endd = os.epoch("utc")
- local dist = endd-start
- print(" took",dist,"ms")
- print("Decrypting with private key:")
- local start = os.epoch("utc")
- local decipher = RSA_Encrypt.decryptStringWithPrivateKey(cipher,priv_key,pub_key)
- if decipher == str then
- print(" success!")
- else
- print(" failed!!")
- print(" got:"..decipher)
- end
- local endd = os.epoch("utc")
- local dist = endd-start
- print(" took",dist,"ms")
- print("\nEncrypting with private key:")
- local start = os.epoch("utc")
- local cipher = RSA_Encrypt.encryptStringWithPrivateKey(str,priv_key,pub_key)
- local endd = os.epoch("utc")
- local dist = endd-start
- print(" took",dist,"ms")
- print("Decrypting with public key:")
- local start = os.epoch("utc")
- local decipher = RSA_Encrypt.decryptStringWithPublicKey(cipher,pub_key)
- if decipher == str then
- print(" success!")
- else
- print(" failed!!")
- print(" got:"..decipher)
- end
- local endd = os.epoch("utc")
- local dist = endd-start
- print(" took",dist,"ms")
- -- print("\nencrypting:")
- -- print(str)
- -- local cipher = RSA_Encrypt.encryptStringWithPublicKey(str,pub_key)
- -- print(cipher)
- -- print("\ndeciphering")
- -- local decipher = RSA_Encrypt.decryptStringWithPrivateKey(cipher,priv_key,pub_key)
- -- print(decipher)
- -- print("\nencrypting:")
- -- print(str)
- -- local cipher = RSA_Encrypt.encryptStringWithPrivateKey(str,priv_key,pub_key)
- -- print(cipher)
- -- print("\ndeciphering")
- -- local decipher = RSA_Encrypt.decryptStringWithPublicKey(cipher,pub_key)
- -- print(decipher)
- end
- return RSA_Encrypt
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement