mirror of
https://github.com/AR2000AR/openComputers_codes.git
synced 2025-09-09 07:01:14 +02:00
initial commit
This commit is contained in:
43
bank_api/bank_api
Normal file
43
bank_api/bank_api
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
NAME
|
||||||
|
bank_api - provide method to communicate with a bank server
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
local bank = require("bank_api")
|
||||||
|
|
||||||
|
DESCIPTION
|
||||||
|
This API allow easy communication with the bank server
|
||||||
|
|
||||||
|
Data structure
|
||||||
|
cbData : see man libCB
|
||||||
|
rawCBdata : see man libCB
|
||||||
|
|
||||||
|
Method list
|
||||||
|
getCredit(cbData):int,int
|
||||||
|
makeTransaction(uuid_cible,cbData,amount):int
|
||||||
|
|
||||||
|
setModemTimeout(t)
|
||||||
|
|
||||||
|
Returned values
|
||||||
|
The first returned value is a status code
|
||||||
|
0 = OK
|
||||||
|
1 = NO_ACCOUNT
|
||||||
|
2 = ERROR_ACCOUNT
|
||||||
|
3 = ERROR_CB
|
||||||
|
4 = ERROR_AMOUNT
|
||||||
|
-1 = timeout
|
||||||
|
-2 = wrong message
|
||||||
|
The second returned value is optional
|
||||||
|
|
||||||
|
CONFIGURATION
|
||||||
|
|
||||||
|
FILES
|
||||||
|
/usr/lib/bank_api.lua
|
||||||
|
the library
|
||||||
|
/etc/bank/api/conf.cfg
|
||||||
|
the config file location
|
||||||
|
|
||||||
|
SEE ALSO
|
||||||
|
libCB
|
||||||
|
|
||||||
|
AUTHOR
|
||||||
|
AR2000
|
142
bank_api/bank_api.lua
Normal file
142
bank_api/bank_api.lua
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
--Bank API by AR2000AR=(AR2000)======
|
||||||
|
--public api used to comunicate with the bank server.
|
||||||
|
--=====================================
|
||||||
|
--LOAD LIB
|
||||||
|
local event = require("event")
|
||||||
|
local serialization = require("serialization")
|
||||||
|
--INIT CONST
|
||||||
|
local BANK_PORT = 351
|
||||||
|
local CONF_DIR = "/etc/bank/api/"
|
||||||
|
local MODEM_TIMEDOUT = -1
|
||||||
|
--INIT COMPONENT
|
||||||
|
local modem = require("component").modem
|
||||||
|
--INIT VAR
|
||||||
|
local bank_addr = "ecdc8d43-5e73-4a9c-ba43-051716c71dc8" --fetched from conf file
|
||||||
|
local timeout = 5
|
||||||
|
|
||||||
|
local bank = {} --table returned by require
|
||||||
|
|
||||||
|
--protocole commands constants
|
||||||
|
local PROTOCOLE_GET_CREDIT = "GET_CREDIT"
|
||||||
|
local PROTOCOLE_MAKE_TRANSACTION = "MAKE_TRANSACTION"
|
||||||
|
local PROTOCOLE_NEW_ACCOUNT = "NEW_ACCOUNT"
|
||||||
|
local PROTOCOLE_NEW_CB = "NEW_CB"
|
||||||
|
--protocole status constants
|
||||||
|
local PROTOCOLE_OK = 0
|
||||||
|
local PROTOCOLE_NO_ACCOUNT = 1
|
||||||
|
local PROTOCOLE_ERROR_ACCOUNT = 2
|
||||||
|
local PROTOCOLE_ERROR_CB = 3
|
||||||
|
local PROTOCOLE_ERROR_AMOUNT = 4
|
||||||
|
local PROTOCOLE_DENIED = 4
|
||||||
|
local PROTOCOLE_ERROR_RECEIVING_ACCOUNT = 5
|
||||||
|
local PROTOCOLE_ERROR_UNKNOWN = 999
|
||||||
|
--=====================================
|
||||||
|
local function reciveMessage() --recive a message from the modem component
|
||||||
|
local _,_,from,port,_,status,command,message = event.pull(timeout,"modem_message")
|
||||||
|
if(not status) then status = MODEM_TIMEDOUT end
|
||||||
|
if(not command) then command = "" end
|
||||||
|
if(not message) then message = "" end
|
||||||
|
return status,command,serialization.unserialize(message)
|
||||||
|
end
|
||||||
|
|
||||||
|
--send a request to the server
|
||||||
|
-- @param requestType:string
|
||||||
|
-- @param requestData:table
|
||||||
|
-- @return status:int,command:string,message:table
|
||||||
|
local function sendRequest(requestType,requestData) --format and send a request to the server
|
||||||
|
modem.open(BANK_PORT)
|
||||||
|
modem.send(bank_addr,BANK_PORT,requestType,serialization.serialize(requestData))
|
||||||
|
local status,command,message = reciveMessage()
|
||||||
|
modem.close(BANK_PORT)
|
||||||
|
return status,command,message
|
||||||
|
end
|
||||||
|
|
||||||
|
--get the account solde
|
||||||
|
-- @param uuid_cible:string
|
||||||
|
-- @param cbData:table
|
||||||
|
-- @param amount:init
|
||||||
|
-- @return int
|
||||||
|
-- -1 : timeout
|
||||||
|
-- -2 : wrong message
|
||||||
|
-- 0 : ok
|
||||||
|
-- 1 : no account
|
||||||
|
-- 2 : account error
|
||||||
|
-- 3 : cb error
|
||||||
|
-- @return solde
|
||||||
|
function bank.getCredit(cbData)
|
||||||
|
local status,command,message = sendRequest(PROTOCOLE_GET_CREDIT,{cbData=cbData})
|
||||||
|
if(status) then
|
||||||
|
if(command == PROTOCOLE_GET_CREDIT) then
|
||||||
|
if(status==PROTOCOLE_OK) then return 0, message.solde
|
||||||
|
elseif(status==PROTOCOLE_NO_ACCOUNT) then return 1, nil
|
||||||
|
elseif(status==PROTOCOLE_ERROR_ACCOUNT) then return 2, nil
|
||||||
|
elseif(status==PROTOCOLE_ERROR_CB) then return 3, nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return -2 --wrong message
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return MODEM_TIMEDOUT --timeout
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- send credit to uuid_cible
|
||||||
|
-- @param uuid_cible:string
|
||||||
|
-- @param cbData:table
|
||||||
|
-- @param amount:init
|
||||||
|
-- @return int
|
||||||
|
-- -1 : timeout
|
||||||
|
-- -2 : wrong message
|
||||||
|
-- 0 : ok
|
||||||
|
-- 1 : no account
|
||||||
|
-- 2 : account error
|
||||||
|
-- 3 : cb error
|
||||||
|
-- 4 : amount error
|
||||||
|
function bank.makeTransaction(uuid_cible,cbData,amount)
|
||||||
|
local status,command,msg = sendRequest(PROTOCOLE_MAKE_TRANSACTION,{dst=uuid_cible,cbData=cbData,amount=amount})
|
||||||
|
if(command == PROTOCOLE_MAKE_TRANSACTION) then
|
||||||
|
return status
|
||||||
|
elseif(status) then
|
||||||
|
return -2 --wrong message
|
||||||
|
else
|
||||||
|
return MODEM_TIMEDOUT --timeout
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function bank.createAccount(secret)
|
||||||
|
local status,command,msg = sendRequest(PROTOCOLE_NEW_ACCOUNT,{secret=secret})
|
||||||
|
if(command == PROTOCOLE_NEW_ACCOUNT) then
|
||||||
|
if(status == PROTOCOLE_OK) then
|
||||||
|
return status,msg.uuid
|
||||||
|
else
|
||||||
|
return status
|
||||||
|
end
|
||||||
|
elseif(status)then
|
||||||
|
return -2
|
||||||
|
else
|
||||||
|
return MODEM_TIMEDOUT
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function bank.requestNewCBdata(secret,accountUUID,cbUUID)
|
||||||
|
local status,command,msg = sendRequest(PROTOCOLE_NEW_CB,{secret=secret,uuid=accountUUID,cbUUID=cbUUID})
|
||||||
|
if(command == PROTOCOLE_NEW_CB) then
|
||||||
|
if(status == PROTOCOLE_OK) then
|
||||||
|
return status, msg.pin, msg.rawCBdata
|
||||||
|
else
|
||||||
|
return status
|
||||||
|
end
|
||||||
|
elseif(status)then
|
||||||
|
return -2
|
||||||
|
else
|
||||||
|
return MODEM_TIMEDOUT
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--set the modem timeout (in s)
|
||||||
|
-- @param t:int
|
||||||
|
function bank.setModemTimeout(t)
|
||||||
|
timeout = t
|
||||||
|
end
|
||||||
|
|
||||||
|
return bank
|
127
bank_dev_tools/accountEdit.lua
Normal file
127
bank_dev_tools/accountEdit.lua
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
local dataCard = require("component").data
|
||||||
|
local fs = require("filesystem")
|
||||||
|
local io = require("io")
|
||||||
|
local os = require("os")
|
||||||
|
local serialization = require("serialization")
|
||||||
|
local shell = require("shell")
|
||||||
|
|
||||||
|
local CONF_DIR = "/etc/bank/server/"
|
||||||
|
local CONF_FILE_NAME = "conf.cfg"
|
||||||
|
local AES_IV = dataCard.md5("bank")
|
||||||
|
|
||||||
|
local keyFile = CONF_DIR.."key" --default value
|
||||||
|
local aesKeyFile = CONF_DIR.."aes" --default value
|
||||||
|
local accountDir = "/srv/bank/" --default value
|
||||||
|
|
||||||
|
local PROTOCOLE_NO_ACCOUNT = 1
|
||||||
|
local PROTOCOLE_ERROR_ACCOUNT = 2
|
||||||
|
|
||||||
|
local function getKey(public)
|
||||||
|
print("-> getKey")
|
||||||
|
local ext = ".priv"
|
||||||
|
local type = "ec-private"
|
||||||
|
if(public) then
|
||||||
|
ext=".pub"
|
||||||
|
type = "ec-public"
|
||||||
|
end
|
||||||
|
local file = io.open(keyFile..ext,"r")
|
||||||
|
local key = dataCard.deserializeKey(dataCard.decode64(file:read("*a")),type)
|
||||||
|
file:close()
|
||||||
|
print("<- getKey")
|
||||||
|
return key
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getAES()
|
||||||
|
local file = io.open(aesKeyFile,"r")
|
||||||
|
local res = file:read("*a")
|
||||||
|
file:close()
|
||||||
|
return dataCard.decode64(res)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function loadAccount(accountUUID)
|
||||||
|
print("-> loadAccount")
|
||||||
|
local account = {}
|
||||||
|
if(fs.exists(accountDir..accountUUID)) then
|
||||||
|
local file = io.open(accountDir..accountUUID,"r")
|
||||||
|
local rawData = file:read("*a") --read the entire file
|
||||||
|
file:close()
|
||||||
|
rawData = dataCard.decode64(rawData)
|
||||||
|
local clearData = dataCard.decrypt(rawData,getAES(),AES_IV) --decrypt the data
|
||||||
|
print("clear data : "..clearData)
|
||||||
|
clearData = serialization.unserialize(clearData) --get the table form the decrypted string
|
||||||
|
if(dataCard.ecdsa(clearData.solde..accountUUID,getKey(true),dataCard.decode64(clearData.sig))) then --check the data signature to prevent manual edition of the file
|
||||||
|
print("<- loadAccount sig ok")
|
||||||
|
return clearData,clearData;
|
||||||
|
else
|
||||||
|
print("<- loadAccount sig err")
|
||||||
|
return PROTOCOLE_ERROR_ACCOUNT,clearData --signature invalide
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print("<- loadAccount no account")
|
||||||
|
return PROTOCOLE_NO_ACCOUNT --account not found
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- write the account file
|
||||||
|
-- @param accountUUID:string
|
||||||
|
-- @param solde:int
|
||||||
|
local function writeAccount(accountUUID,solde)
|
||||||
|
print("-> writeAccount")
|
||||||
|
local account = {solde=solde,uuid=accountUUID}
|
||||||
|
account.sig = dataCard.encode64(dataCard.ecdsa(solde..accountUUID,getKey(false))) --encode sig to make saving it easier
|
||||||
|
local fileContent = serialization.serialize(account) --convert the table into a string
|
||||||
|
fileContent = dataCard.encrypt(fileContent,getAES(),AES_IV) --encrypt the data
|
||||||
|
fileContent = dataCard.encode64(fileContent) --encode the encrypted data to make saving and reading it easier
|
||||||
|
io.open(accountDir..accountUUID,"w"):write(fileContent):close() --save the data
|
||||||
|
print("<- writeAccount ")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- handle account edition (check if the account exists and add amount to it's solde)
|
||||||
|
-- @param uuid:string
|
||||||
|
-- @param amount:ini
|
||||||
|
-- @return boolean
|
||||||
|
local function editAccount(accountUUID,amount)
|
||||||
|
local account = loadAccount(accountUUID)
|
||||||
|
if(account == PROTOCOLE_NO_ACCOUNT or account == PROTOCOLE_ERROR_ACCOUNT) then --check for errors with the account
|
||||||
|
return false --give up
|
||||||
|
else
|
||||||
|
writeAccount(account.uuid,account.solde + amount)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--MAIN=================================
|
||||||
|
if(fs.exists(CONF_DIR..CONF_FILE_NAME))then --read the config file
|
||||||
|
local file=io.open(CONF_DIR..CONF_FILE_NAME,"r")
|
||||||
|
local confTable = serialization.unserialize(file:read("*a"))
|
||||||
|
file:close()
|
||||||
|
if(confTable.accountDir)then accountDir = confTable.accountDir end
|
||||||
|
if(confTable.aesKeyFile)then aesKeyFile = confTable.aesKeyFile end
|
||||||
|
if(confTable.keyFile)then keyFile = confTable.keyFile end
|
||||||
|
else
|
||||||
|
io.stream(2):write("NO CONFIG FILE FOUND IN "..CONF_DIR)
|
||||||
|
os.exit()
|
||||||
|
end
|
||||||
|
|
||||||
|
local args,opts = shell.parse(...)
|
||||||
|
if(args[1]=="get") then
|
||||||
|
ac=loadAccount(args[2])
|
||||||
|
if(type(ac)=="number")then
|
||||||
|
print("err:"..ac)
|
||||||
|
else
|
||||||
|
print(ac.solde)
|
||||||
|
end
|
||||||
|
elseif(args[1]=="set") then
|
||||||
|
writeAccount(args[2],tonumber(args[3]))
|
||||||
|
print("done")
|
||||||
|
elseif(args[1]=='test') then
|
||||||
|
_,clearData = loadAccount(args[2])
|
||||||
|
local b,c = 0,0
|
||||||
|
b=dataCard.ecdsa(clearData.solde..args[2],getKey(true),dataCard.decode64(clearData.sig))
|
||||||
|
c=dataCard.encode64(dataCard.ecdsa(clearData.solde..args[2],getKey(false)))
|
||||||
|
print(b)
|
||||||
|
print("saved: "..clearData.sig)
|
||||||
|
print("calc : "..c)
|
||||||
|
else
|
||||||
|
print("accountEdit <get/set> <uuid> [ammount]")
|
||||||
|
end
|
37
libCB/libCB
Normal file
37
libCB/libCB
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
NAME
|
||||||
|
libCB - provide a way to use credit card
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
local libCB = require("libCB")
|
||||||
|
|
||||||
|
DESCIPTION
|
||||||
|
Use this lib to access a credit card. A credit card is a special unmanaged floppy disk
|
||||||
|
|
||||||
|
Data structure
|
||||||
|
cbData:table
|
||||||
|
uudi, --account uuid
|
||||||
|
cbUUID, --card uuid
|
||||||
|
sig --card signature made form uuid & card's drive component's uuid
|
||||||
|
|
||||||
|
rawCBdata:table
|
||||||
|
uudi, --account uuid
|
||||||
|
sig --card signature made form uuid & card's drive component's uuid
|
||||||
|
pink_check
|
||||||
|
|
||||||
|
Method list
|
||||||
|
getCB(cbDrive,pin):cbData
|
||||||
|
cbDrive:uuid > the drive component address of the cb
|
||||||
|
pin:str > user pin code
|
||||||
|
|
||||||
|
Returned values
|
||||||
|
cbData
|
||||||
|
|
||||||
|
FILE
|
||||||
|
/usr/lib/libCB.lua
|
||||||
|
the library
|
||||||
|
|
||||||
|
SEE ALSO
|
||||||
|
bank_api
|
||||||
|
|
||||||
|
AUTHOR
|
||||||
|
AR2000
|
78
libCB/libCB.lua
Normal file
78
libCB/libCB.lua
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
--libCB by AR2000AR=(AR2000)==========
|
||||||
|
--manage credit card (unmanaged floppy)
|
||||||
|
--=====================================
|
||||||
|
local cb = {} --table returned by require
|
||||||
|
local data = require("component").data --data component used for cryptocraphic stuf
|
||||||
|
local serialization = require("serialization") --data serialization and unserialization
|
||||||
|
|
||||||
|
--read the credit card data and return it
|
||||||
|
-- @param cbDrive:proxy the floppy's component
|
||||||
|
local function readCB(cbDrive)
|
||||||
|
local i = 1
|
||||||
|
--get the data from the card
|
||||||
|
--the card is in unmanaged mode (binary) and the data is writen at the start of
|
||||||
|
--the floppy disk
|
||||||
|
local rawData = cbDrive.readSector(1):gsub("\0","") --clean null byte after the data
|
||||||
|
local cbData = serialization.unserialize(rawData)
|
||||||
|
cbData.cbUUID = cbDrive.address
|
||||||
|
return cbData
|
||||||
|
end
|
||||||
|
|
||||||
|
function cb.getCB(cbDrive,pin)
|
||||||
|
local res = readCB(cbDrive)
|
||||||
|
res.uuid = data.decrypt(data.decode64(res.uuid),data.md5(res.cbUUID),data.md5(pin))
|
||||||
|
local pin_check = false
|
||||||
|
pin_check = data.decrypt(data.decode64(res.pin_check),data.md5(res.cbUUID),data.md5(pin)) == "PIN"
|
||||||
|
if(pin_check) then
|
||||||
|
return res
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- check if the cb is valide
|
||||||
|
-- @param cbData:table (see man libCB for more info about cbData)
|
||||||
|
-- @param publicKey:userdata
|
||||||
|
-- @return boolean
|
||||||
|
function cb.checkCBdata(cbData,publicKey)
|
||||||
|
return data.ecdsa(cbData.uuid..cbData.cbUUID..cbData.pin_check,publicKey,data.decode64(cbData.sig))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- generate a random 4 digit pin
|
||||||
|
-- @return string
|
||||||
|
local function randomPin()
|
||||||
|
local pin = ""..math.random(9999)
|
||||||
|
while (#pin < 4) do
|
||||||
|
pin = "0"..pin
|
||||||
|
end
|
||||||
|
return pin
|
||||||
|
end
|
||||||
|
|
||||||
|
-- create a new rawCBdata
|
||||||
|
-- @param uuid:string account uuid
|
||||||
|
-- @param cbUUID:string new cb's uuid
|
||||||
|
-- @param privateKey:userdata key used to sign the cb
|
||||||
|
-- @retrun rawCBdata:table
|
||||||
|
-- @return pin:string
|
||||||
|
function cb.createNew(uuid,cbUUID,privateKey)
|
||||||
|
local pin = randomPin()
|
||||||
|
local aesKey = data.md5(cbUUID)
|
||||||
|
local aesIV = data.md5(pin)
|
||||||
|
local newCB = {}
|
||||||
|
newCB.uuid = data.encode64(data.encrypt(uuid,aesKey,aesIV))
|
||||||
|
newCB.pin_check = data.encode64(data.encrypt("PIN",aesKey,aesIV))
|
||||||
|
newCB.sig = data.ecdsa(uuid..cbUUID..newCB.pin_check,privateKey)
|
||||||
|
newCB.sig = data.encode64(newCB.sig)
|
||||||
|
return newCB,pin
|
||||||
|
end
|
||||||
|
|
||||||
|
-- write rawCBdata to a unmanaged floppy
|
||||||
|
-- @param rawCBdata:table the table provided by cb.createNew(...)
|
||||||
|
-- @param cbDrive:proxy the floppy's component proxy
|
||||||
|
function cb.writeCB(rawCBdata,cbDrive)
|
||||||
|
local buffer = serialization.serialize(rawCBdata)
|
||||||
|
cbDrive.writeSector(1,buffer)
|
||||||
|
cbDrive.setLabel("CB")
|
||||||
|
end
|
||||||
|
|
||||||
|
return cb --return the table containing all the public functions
|
Reference in New Issue
Block a user