I like this a lot thanks.
Here is a vertical version I made modifying yours.  I also fixed it so you can use os.pullEvent = os.pullEventRaw to prevent termination and added 0 to the numbers.  When setting the unlock code u must use 10 to represent 0.  So 34510 would be 3450 to unlock.

See this for the fix:
for i = 1, #buttons do
-- if there is no value do nothing (for when termination is being attempted)
	   if y ~= nill then
		  if y >= buttons[i]["ymin"] and y <= buttons[i]["ymax"] then
			if x >= buttons[i]["xmin"] and x <= buttons[i]["xmax"] then
			
			  buttons[i]["active"] = not buttons[i]["active"]
			  refreshButtons()
			  sleep(0.2)
			  buttons[i]["active"] = not buttons[i]["active"]
			  refreshButtons()
			  clicked = i
			  if buttons[i]["func"] ~= nil then
				buttons[i]["func"]()
			  
			  
			  end
			end
		  end
		end
	end
Get program:
pastebin get nSXX0mbx lock
Full code for vertical style:
os.pullEvent = os.pullEventRaw
--monitor side
monitorside = "top"
--redstone side
outputside = "left"
--pasword
pass = "1234"
--Countdown timer
waittime = 10
m = peripheral.wrap(monitorside)
x,y = m.getSize()
--button on/off color
bactive = colors.cyan
binactive=colors.gray
--text on/off color
tactive=colors.white
tinactive=colors.white
--Background color
bgcolor = colors.black
function printCentered(text,y)
m.setCursorPos(x/2 - #tostring(text)/2,y)
m.write(text)
end
buttons = {}
	  function newButton(id,xmin,xmax,ymin,ymax,text,func)
		buttons[id] = {}
		buttons[id]["xmin"] = xmin
		buttons[id]["xmax"] = xmax
		buttons[id]["ymin"] = ymin
		buttons[id]["ymax"] = ymax
		buttons[id]["active"] = false
		buttons[id]["text"] = text
		buttons[id]["func"] = func
	  end
	  ---------------------------------------------------------------------------------
	  function printButton(id)
		ymin = buttons[id]["ymin"]
		ymax = buttons[id]["ymax"]
		xmin = buttons[id]["xmin"]
		xmax = buttons[id]["xmax"]
		text = buttons[id]["text"]
		ia = buttons[id]["active"]
			width = xmax - xmin
			height = ymax - ymin
			if ia then m.setBackgroundColor(bactive) m.setTextColor(tactive)
			else m.setBackgroundColor(binactive) m.setTextColor(tinactive) end
			for j = ymin,ymax do
			 m.setCursorPos(xmin,j)
			  for i = xmin,xmax do
				m.write(" ")
			 end
		   end
		m.setCursorPos(xmin + width / 2 - #text / 2 + 1,ymin + height / 2)
	   m.write(text)
	   m.setBackgroundColor(bgcolor)
	  end
	  ----------------------------------------------------------------------------------
	  function refreshButtons()
		for i = 1,#buttons do
		  printButton(i)
		end
	  end
	function checkxy( x,y )
	  for i = 1, #buttons do
		if y ~= nill then
		  if y >= buttons[i]["ymin"] and y <= buttons[i]["ymax"] then
			if x >= buttons[i]["xmin"] and x <= buttons[i]["xmax"] then
			  buttons[i]["active"] = not buttons[i]["active"]
			  refreshButtons()
			  sleep(0.2)
			  buttons[i]["active"] = not buttons[i]["active"]
			  refreshButtons()
			  clicked = i
			  if buttons[i]["func"] ~= nil then
				buttons[i]["func"]()
			  end
			end
		  end
		end
	  end
	end
permbactive = bactive
function countDown(time)
m.clear()
for i = time, 0, -1 do
m.setCursorPos(9,3)
if i >= 10 then
i = string.sub(i,1,2)
else
i = string.sub(i,1,1)
end
m.clearLine(3)
if tonumber(i) > time / 2 then
m.setTextColor(colors.lime)
elseif tonumber(i) > time / 4 then
m.setTextColor(colors.orange)
elseif tonumber(i) > time / 8 then
m.setTextColor(colors.red)
end
m.write(i)
sleep(1)
end
m.clear()
end
function allButtons(active)
for i = 1, #buttons do
buttons[i]["active"] = active
refreshButtons()
end
end
function blink(color)
bactive = color
allButtons(true)
sleep(.2)
allButtons(false)
sleep(.2)
allButtons(true)
sleep(.2)
allButtons(false)
sleep(.2)
bactive = permbactive
end
checkpass = ""
function append()
if clicked ~= 11 then
checkpass = checkpass..clicked
else
checkpass = ""
end
if #checkpass == #pass then
if checkpass == pass then
blink(colors.lime)
rs.setOutput(outputside, true)
countDown(waittime)
rs.setOutput(outputside, false)
checkpass = ""
else
blink(colors.red)
checkpass = ""
end
end
clicked = nil
end
newButton(1, 1,3,1,1,"1",append)
newButton(2, 5,7,1,1,"2",append)
newButton(3, 1,3,3,3,"3",append)
newButton(4, 5,7,3,3,"4",append)
newButton(5, 1,3,5,5,"5",append)
newButton(6, 5,7,5,5,"6",append)
newButton(7, 1,3,7,7,"7",append)
newButton(8, 5,7,7,7,"8",append)
newButton(9, 1,3,9,9,"9",append)
newButton(10, 5,7,9,9,"0",append)
newButton(11, 1,7,11,11,"C",append)
------------------------------------------------
m.clear()
refreshButtons()
--main loop
while true do
e,side,x,y = os.pullEvent("monitor_touch")
checkxy(x,y)
refreshButtons()
end