Advertisement
theinsekt

hsign3

Sep 18th, 2014
193
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.65 KB | None | 0 0
  1. --theinsektAPIs/hsign3
  2. --experiment3, not tested!
  3. --have changed so that older or same age messages than the last ok message,
  4. --will be considered invalid
  5. --This so that the same command can't be retransmitted by an attacker
  6.  
  7. --a signer: signs a message and turns it into a sendable string
  8. --a verifier: verifies the sendable string and returns ok,message2, where ok is true or false, and message2 is the
  9. --message that was signed
  10. --so if you do: local ok, message2=verify(sign(message))
  11. --then message2 will be equal to message, and ok will true
  12. --if someone fails at forging a message then ok will be false and message2 will be nil
  13.  
  14. --example usage (not tested!):
  15. --os.loadAPI("theinsektAPIs/sha256")
  16. --local protocol="myprotocolname"
  17. --local secret="mysupersecret"
  18. ----use this for sending
  19. --local sign=hsign2.getPack(secret,sha256.sha256)--do once
  20. --rednet.send(id,sign("my message, can be any type of data"),protocol)
  21. --rednet.send(id,sign("message2"),protocol)
  22. ----use this for receiving
  23. --local maxDelay=7 --7 seconds old messages will be considered invalid
  24. --local verify=hsign2.getUnpack(secret,sha256.sha256,maxDelay)--do once
  25. --local id, signedMessage,protocol=rednet.receive(protocol,timeout)
  26. --local ok,message=verify(signedMessage)--call directly after receive, because calculates time received inside
  27. -- if not ok then print("message was invalid") end
  28. --id, signedMessage,protocol=rednet.receive(protocol,timeout)
  29. --ok,message=verify(signedMessage)
  30. -- if not ok then print("message was invalid") end
  31.  
  32.  
  33.  
  34. --returns a pack function, that can be used to turn a message into a packet ready for sending
  35. --over rednet
  36. function getSigner(secret, hashFunction)
  37.   return function(message)
  38.     --prepare the box that holds the data, and a time stamp
  39.     local box={time0=os.time(),day0=os.day(), data=message,}
  40.     --turn the box into a string
  41.     local serializedBox=textutils.serialize(box)
  42.     --put it in a table, and put hash of it+secret
  43.     local packet={
  44.       ["box"]=serializedBox,
  45.       ["hash"]=hashFunction(serializedBox..secret),
  46.     }
  47.     --return the prepared packet
  48.     return textutils.serialize(packet)
  49.   end
  50. end
  51.  
  52. --might stop working if an admin turns back time
  53. --returns a unpack function that can unpack a packet, from the correspaonding pack function
  54. function getVerifier(secret,hashFunction,maxDelay)
  55.   --save some values from the last ok hash
  56.   --so that an attacker can't send copies
  57.   --unless this computer restarts within maxDelay after message
  58.   local lastTime=os.time()
  59.   local lastDay=os.day()
  60.   local lastHash=nil --might be unnecessary
  61.  
  62.   --this is to protect against resent commands after computer has restarted
  63.   if maxDelay==nil then maxDelay=10 end
  64.  
  65.   return function(packet)
  66.     --get the time that the packet was received
  67.     local time2=os.time()
  68.     local day2=os.day()
  69.  
  70.     --NEW
  71.     --check if need to correct last lastTime or lastDay
  72.     --this can happen if admin chamges ingame time to an earlier time value
  73.     --some ok messages will become invalid
  74.     if day2<lastDay or (day2==lastDay and time2<lastTime) then
  75.       lastDay=day2
  76.       lastTime=time2
  77.     end
  78.  
  79.     if type(packet)~="string" then
  80.       return false,nil
  81.     end
  82.  
  83.     packet=textutils.unserialize(packet)
  84.     --type check packet and packet fields
  85.     if type(packet)~="table" or type(packet["box"])~="string" or type(packet["hash"])~="string" then
  86.       return false, nil
  87.     end
  88.  
  89.     --get and unserialize box
  90.     local serializedBox=packet["box"]
  91.     local box=textutils.unserialize(serializedBox)
  92.  
  93.     --type check box
  94.     if type(box)~="table" or type(box["time0"])~="number" or type(box["day0"])~="number" then
  95.       return false, nil
  96.     end
  97.  
  98.     --CHANGED
  99.     --check that time stamps aren't to old
  100.     local delay1=timeDiff(time2,day2,box["time0"],box["day0"])
  101.     if delay1>maxDelay then
  102.       return false, nil
  103.     end
  104.  
  105.     --NEW
  106.     --check that the time stamps in the packet isn't from the future
  107.     --this can happen if a message is created, the ingame time is turned back, and the message is received
  108.     --then previously sent commands could be accepted even though they are old commands
  109.     --This could still happen if attacker resends old new command before maxDelay after the time stamp
  110.     if delay1<0 then
  111.       return false, nil
  112.     end
  113.  
  114.  
  115.  
  116.     --check that the hash is correct
  117.     --this is so that only someone with the secret can send a message that is ok
  118.     local hashValue=hashFunction(serializedBox..secret)
  119.     if hashValue~=packet["hash"] then
  120.       return false, nil
  121.     end
  122.  
  123.     --check that the same message haven't been sent
  124.     --this is so that the same command message can't be resent by an attacker
  125.     if packet["hash"]==lastHash then
  126.      return false, nil
  127.     end
  128.  
  129.     --CHANGED
  130.     --check that the time stamp isn't earlier than the last ok message
  131.     --this is so that an earlier command can't be sent by an attacker to override a later command
  132.     local delay2=timeDiff(lastTime,lastDay,box["time0"],box["day0"])
  133.     if delay2>0 then
  134.       return false, nil
  135.     end
  136.  
  137.     --passed all tests
  138.    
  139.     --update latest ok message hash
  140.     --update latest ok message time
  141.     lastHash=packet["hash"]
  142.     lastTime=box["time0"]
  143.     lastDay=box["day0"]
  144.    
  145.     --return ok and message
  146.     return true, box["data"]
  147.   end
  148. end
  149.  
  150.  
  151.  
  152.  
  153. --returns the time difference in seconds
  154. --is used in verifier
  155. --the returned value is like taking t1-t2
  156. function timeDiff(time1,day1,time2,day2)
  157.   --converts to minecraft ingame hours
  158.   local minecraftDiff=(day1-day2)*24+(time1-time2)
  159.   --converts to real seconds
  160.   local secondsDiff=minecraftDiff*((20/24)*60)
  161.   return secondsDiff
  162. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement